什麼是正規表示法#
正規表示法(Regular Expression, regex)是一套用特殊符號描述字串模式的語法。它不是一個程式,而是一種被其他工具支援的語法標準。支援正規表示法的工具包括 grep、sed、awk、vim、Python、JavaScript 等。
正規表示法的價值在於:用簡短的模式描述,就能匹配大量符合規則的字串。這在搜尋 log、驗證輸入格式、批次文字處理等場景中不可或缺。
正規表示法 vs. 萬用字元#
初學者常混淆這兩者,但它們是完全不同的機制:
| 萬用字元(Globbing) | 正規表示法(Regex) | |
|---|---|---|
| 使用場景 | Shell 的檔案名稱匹配 | 文字內容的模式匹配 |
* 的意義 | 匹配任意字元(零或多個) | 前一個字元重複零或多次 |
| 處理者 | Shell 本身 | grep、sed、awk 等工具 |
這是最常見的混淆點。Shell 的
ls *.txt中的*是萬用字元,由 Shell 展開為符合的檔名。而grep 'a*' file中的*是正規表示法,表示「前面的 a 重複零次或多次」。兩者語法相似但意義完全不同。
基礎正規表示法#
核心語法元素#
| 符號 | 意義 |
|---|---|
. | 匹配任意一個字元 |
* | 前一個字元重複零次或多次 |
^ | 行首定位 |
$ | 行尾定位 |
[] | 字元集合,匹配其中任一個 |
[^] | 反向字元集合,不匹配其中任何一個 |
\{n\} | 前一個字元恰好重複 n 次 |
\{n,m\} | 前一個字元重複 n 到 m 次 |
語系對正規表示法的影響#
字元的排序方式取決於語系設定(LANG):
LANG=C:按 ASCII 碼排序(0-9A-Za-z)LANG=zh_TW.UTF-8:大小寫交錯排序(aAbBcC...)
在使用
[a-z]這類範圍表示時,語系設定會直接影響匹配結果。建議在 script 中使用字元類別(如[:lower:]、[:upper:]、[:digit:])來避免語系差異帶來的問題。
sed:串流編輯器#
sed(Stream Editor)是一個非互動式的文字處理工具,以串流的方式逐行處理文字。它的設計哲學是:不需要開啟檔案、不需要互動操作,就能完成批次的文字替換與修改。
sed 的主要操作:
- 刪除特定行
- 替換匹配的文字
- 新增/插入行
- 直接修改檔案內容(
-i選項)
sed 在 CI/CD pipeline 和自動化腳本中極為常用——批次修改設定檔、處理 log 輸出、過濾特定格式的資料。
延伸正規表示法#
基礎正規表示法中某些語法寫起來較繁瑣,延伸正規表示法(ERE)提供了更簡潔的寫法:
| 符號 | 意義 |
|---|---|
+ | 前一個字元重複一次或多次 |
? | 前一個字元出現零次或一次 |
| | 或(OR),匹配其中任一模式 |
() | 群組,將多個字元視為一個單元 |
grep預設使用基礎正規表示法。要使用延伸正規表示法,需要用grep -E(或egrep)。
awk:欄位導向的資料處理#
awk 的核心思想是將每一行文字按分隔符號切割成多個欄位,然後針對欄位進行操作。它特別適合處理結構化的文字資料(如 /etc/passwd、CSV、log 檔)。
awk 的運作邏輯:
- 逐行讀取輸入
- 按分隔符號將每行切割成
$1、$2、$3…($0是整行) - 依條件判斷是否處理該行
- 執行指定的動作
grep、sed、awk 常被稱為 Linux 文字處理的「三劍客」:
- grep 擅長搜尋——找出包含特定模式的行
- sed 擅長替換——批次修改文字內容
- awk 擅長分析——按欄位處理結構化資料
檔案比對工具#
- diff:逐行比對兩個文字檔的差異,輸出可作為
patch的輸入 - cmp:逐 byte 比對,適合二進位檔案
- patch:根據
diff的輸出,將修改套用到檔案上
diff+patch的組合是版本控制的原始形態。Git 的 diff 功能就是建立在類似的原理上。理解這個機制,有助於理解 Git 如何追蹤和管理程式碼變更。