Regex 進階用法 - Lookbehind 與 lookahead

前言 正規表達式(Regex)是文字處理中的重要工具,無論是搜尋、驗證表單還是數據清理都非常常見,或是客製化 config 檔時也能透過正則表達式設計更複雜的邏輯。 而進階技巧如 Lookbehind 和 Lookahead 則讓開發者能夠撰寫更精確的表達式。這些特性幫助我們在匹配特定內容時可以加上前後文條件,卻不將這些條件納入匹配結果中。 本文將紀錄 Lookbehind 和 Lookahead 的概念、其運作方式,並提供一些實際範例來紀錄這些進階用法。 Zero-Width Assertions 首先,在介紹 Lookahead 和 Lookbehind 這兩個表達式以前,要先知道一個叫做 Zero-Width Assertions 的概念 (中文不知道怎麼翻譯,就直接用英文表示)。 Zero-Width Assertions 是指那些僅匹配文本中的特定位置,而非具體字符的語法或表達式。 它們會在想要匹配的字串中的某個位置檢查特定條件,但不會消耗任何字符,也不會使正則表達式引擎的游標向前推進。因此,這類斷言經常被稱為「隱形」條件,能夠在不影響最終匹配結果的情況下,讓我們定義更複雜的匹配模式。 聽起來有點抽象,簡單來說概念就像是 regex 世界的 if/else,可以做一些邏輯的判定。 常見的 Zero-Width Assertions 有底下三種: Lookahead Lookbehind Anchor (^, $) 前面兩個我們先忽略,因為等等後面會一一介紹。第三個 Anchor 仔細看會發現就是我們平常在用的字串起始(^)與字串結尾($) 快速舉個例子來說, ^Helloween$ 這個表達式可以匹配到 “Helloween” 這個字串,但不會匹配到 “~Helloween” 和 “Helloween~” 這兩個字串,原因是我們明確指定字串要以 H 開頭且以 n 結尾。 當使用 Anchor 這類的 Zero-Width Assertions 表達式,並不會消耗我們的字元,意思是他只會拿來做為邏輯的判定(是否以某字元做起始? 是否以某字元做結尾?),這樣會帶來幾點好處: 可以根據上下文設定匹配的邏輯判定(某文字之前或之後),而不會影響實際匹配的內容 消除不必要的 backtracking 來避免效能的減損 (Catastrophic Backtracking) ahead vs behind 要介紹 Lookahead 和 Lookbehind 之前,要先定義到底什麼是 ahead?...

<span title='2024-10-25 18:12:13 +0800 +0800'>October 25, 2024</span>&nbsp;·&nbsp;2 min&nbsp;·&nbsp;267 words&nbsp;·&nbsp;Madi

MySQL 資料修復 (Force InnoDB Recovery)

前言 在日常維運中,MySQL 的數據庫可能因各種原因遭到損壞,例如硬碟故障、斷電等。最近工作上就遇到客戶環境出現異常的現象,資料庫疑似寫入壞資料導致 MySQL 不斷跳出此錯誤 Operation cannot be performed. The table 'xxx' is missing, corrupt or contains bad data. 當下處理時還一頭霧水,因為根本無法查詢資料,SELECT 資料時,該資料表都會跳出此錯誤訊息,連資料都無法 query,又該怎麼知道哪裡有壞資料呢? Forcing InnoDB Recovery 針對這種棘手的情況 MySQL 提供了 InnoDB 強制恢復模式(InnoDB Force Recovery) 來協助修復損壞數據。此模式允許管理人員在無法啟動的情況下訪問資料並嘗試進行修復。 MySQL 設定檔 以下是用 MySQL 5.7.30 的環境 具體操作如下: 首先,要先找到 MySQL 的設定檔 (my.cnf),通常會位於底下幾種路徑 (Docker container 也是一樣) /etc/my.cnf /etc/mysql/my.cnf $MYSQL_HOME/my.cnf [datadir]/my.cnf ~/.my.cnf 如果都找不到的話,可以執行 mysql --help,從輸出的 log 中去找 my.cnf 可能的檔案路徑 Default options are read from the following files in the given order: /etc/my....

<span title='2024-10-20 19:49:13 +0800 +0800'>October 20, 2024</span>&nbsp;·&nbsp;2 min&nbsp;·&nbsp;219 words&nbsp;·&nbsp;Madi

MySQL 備份筆記

前言 最近工作的專案是使用 Java SpringBoot 搭配 MySQL 資料庫做數據儲存與管理,部署在客戶環境時需要備份資料,為了有效地完成備份工作,使用 MySQL 常見的備份工具 - mysqldump,但過程中牽涉到很多參數的用途,所以有了這篇文章做紀錄,以供未來參考 什麼是 mysqldump? mysqldump 是 MySQL 提供的一個命令行工具,用於備份資料庫。它可以生成 SQL 語句,這些語句可以用於重建資料庫的結構和數據。這使得 mysqldump 成為一個非常靈活且易於使用的備份解決方案 基本語法 mysqldump [options] database [tables] database 是你要備份的資料庫名稱 tables 是可選的,表示你可以指定要備份的特定表 常用用途 備份整個資料庫 要備份整個資料庫,可以使用以下指令: mysqldump -u username -p database_name > backup.sql -u: 用於指定用戶名 -p: 會提示輸入密碼 backup.sql: 是你要生成的備份文件名 備份特定表 如果只想備份特定的表,可以這樣做: mysqldump -u username -p database_name table1 table2 > backup.sql 這將備份 table1 和 table2 兩個表 常用參數 (Options) 底下列出在實際備份時,個人有使用到的一些參數,如果要了解全部的參數意義,可參考 官方文件 需格外注意的是 MySQL 有區分幾種 engine,最常見的就是 MyISAM 和 InnoDB,前者是 non-transactional,後者才是 transactional,這會影響到備份時是否需要鎖表,以及帶來的效能影響與資料一致性的差異...

<span title='2024-09-10 19:49:13 +0800 +0800'>September 10, 2024</span>&nbsp;·&nbsp;2 min&nbsp;·&nbsp;241 words&nbsp;·&nbsp;Madi

[小專案] 自動辨識藥丸數量的網站

前言 前陣子我的藥師朋友經常需要手動計數藥丸,以便進行包藥作業.這個過程既耗時又容易出錯。為了解決這一問題,我幫他設計了一個簡單的應用程式,使用 YOLOv8 模型來自動識別並計算照片中藥丸的數量,從而快速提供準確的結果 專案說明 專案的詳細介紹我把他整理到 Notion 上,裏面有更詳細的說明 Ref: GitHub Repo 系統架構 這個專案需求非常簡單,其實單純一個 Monolithic 的架構就可以應付,但為了練習看看微服務(Micro service)的切分,就嘗試將不同的功能切分成不同的服務,彼此用 Restful API 溝通 Tech Stack 簡單列一下使用到的技術 Backend Python(FastAPI) Node.js(Express) written in TypeScript Auth JWT Google Auth Redis AI Model YOLOv8 Label-Studio (Labeling Tool) Frontend React written in TypeScript PWA Storage PostgreSQL (database) Minio (Image storage) 心得 這是第一次嘗試 React 的 PWA,用 service worker 滿直覺也滿簡單的,配置一下部署到 Netlify 上,就可以把網站下載到手機桌面上充當一個 APP 使用 這是第一次嘗試 Yolov8 的模型,並使用 Label-Studio 工具作為標註,使用起來相當直覺,當有多人需要同時標註時,簡單在電腦啟動 server,然後用 ngrok 臨時建個 tunnel,開放給別人一起標註...

<span title='2024-07-29 15:50:04 +0800 +0800'>July 29, 2024</span>&nbsp;·&nbsp;2 min&nbsp;·&nbsp;214 words&nbsp;·&nbsp;Madi

整理 PostgreSQL 的 Index 類型

前言 索引(Index)類型的選擇對於資料庫效能的優化至關重要,不同的索引類型適用於不同的查詢和資料結構。近期開發常常會接觸到 PostgreSQL,所以順手整理幾種常見的 PostgreSQL 索引類型及其適用場景 索引類型 B-tree B-tree 是 PostgreSQL 中最常用的索引類型,也是 PostgreSQL 建立索引時,未指名索引類型時預設的索引類型 B-tree 中的每個節點通常包含多個 key-value pair,其中 key 用於索引,value 指向表中相應的資料 它適用於以下幾種查詢: 比較操作:<、>、>=、<= 區間查詢:BETWEEN 空值查詢:IS NULL 語法如下 -- 建立 table 的索引 CREATE INDEX index_name ON table_name; -- 建立單獨 column 的索引 CREATE INDEX index_name ON table_name (column_name); Hash Hash 索引是應用 hash 的特性來達到快速查詢的情境.適合需要判定相等(equality check)的查詢: 相等:= 存在:IN 遇到資料異動(INSERT, UPDATE, DELETE)的時候,為了解決 hash 碰撞(collision)和重製資料(rehash data),維護 hash 的行爲會比 B-tree 帶來更昂貴的成本. 除此之外,雖然 Hash 索引在等值查詢上的效能非常好,但它在範圍查詢(range query)和排序(sorting)的情境上不及 B-tree 來得適合,因此在使用上需要特別小心,一般來說在沒有特殊要求下,使用 B-tree 已能滿足整體效能需求...

<span title='2024-06-18 20:50:04 +0800 +0800'>June 18, 2024</span>&nbsp;·&nbsp;3 min&nbsp;·&nbsp;541 words&nbsp;·&nbsp;Madi