正規表示式 regex 速成指南
在 Linux 系統管理的日常工作中,文字處理佔據了極大的比重。無論是檢視日誌檔、過濾設定檔,還是批量重命名檔案,正規表示式(Regular Expression,簡稱 regex)都是我們手中最強大的武器。許多初學者往往被 regex 複雜的語法嚇退,但實際上,掌握核心概念後,它能將原本需要數小時的手動操作縮短至秒級完成。本文將針對 Ubuntu 22.04 / Debian 12 環境,深入解析最常用的 grep 指令及其 regex 應用。
基礎語法與核心概念
正規表示式並非單一語言,而是一套描述字串模式的標準。在 Linux 中,我們主要區分為基礎正規表示式(BRE)與擴充正規表示式(ERE)。現代 Linux 工具大多支援 ERE,語法更為直觀。
1. 字元類別與定位符
最基礎的匹配是精確字串,但 regex 的強大在於「模式」。例如,^ 代表行的開頭,$ 代表行的結尾。
假設我們有一個名為 users.txt 的檔案,內容如下:
alice
bob
charlie
alice@domain.com
root
若要找出以 alice 開頭的行,我們使用 grep 搭配 ^:
grep '^alice' users.txt
輸出結果僅顯示:
alice
alice@domain.com
若我們只想找出「單獨一行」為 alice 的記錄(排除 alice@domain.com),則需同時指定結尾符號:
grep '^alice$' users.txt
輸出結果僅為:
alice
2. 萬用字元與字元組
在 regex 中,.(點號)代表「任意單一字符」,而非檔案系統中的萬用字元。若要匹配特定範圍內的字符,我們使用方括號 [ ]。
假設我們要過濾出包含數字 1 到 3 的 IP 地址片段:
echo "IP: 192.168.1.1, IP: 192.168.4.1" | grep -o '[1-3]\.'
這裡 -o 選項僅輸出匹配的部分。結果將顯示:
1.
1.
若使用擴充正規表示式(ERE),語法會更簡潔。在 grep 中加上 -E 選項即可啟用:
echo "error: 404 not found" | grep -E 'error: [0-9]+'
這裡 [0-9]+ 表示匹配一個或多個數字。輸出為:
error: 404 not found
進階應用:處理系統日誌
在實際工作中,我們常需從 /var/log/syslog 或 journalctl 輸出中篩選特定錯誤。假設我們想找出所有包含 error 或 Error 且行首帶有時間戳記的記錄。
首先,建立一個模擬日誌檔 log.txt:
2023-10-01 10:00:00 INFO Service started
2023-10-01 10:01:00 ERROR Connection failed
2023-10-01 10:02:00 info retrying...
2023-10-01 10:03:00 error timeout
若我們要忽略大小寫並找出所有錯誤相關行,使用 -i 選項:
grep -i 'error' log.txt
輸出:
2023-10-01 10:01:00 ERROR Connection failed
2023-10-01 10:03:00 error timeout
若我們想進一步過濾,只保留「ERROR」或「error」且後面緊接空格的行,可以使用擴充 regex 的「或」運算子 |:
grep -E 'ERROR\s|error\s' log.txt
注意:在基礎 grep 中 \s 可能不被支援,建議使用 [[:space:]] 或直接使用空格。在支援 PCRE(Perl Compatible Regular Expressions)的 grep -P 中,\s 才能正常工作。在 Debian/Ubuntu 預設環境中,推薦使用以下兼容寫法:
grep -E '(ERROR|error) ' log.txt
常見問題與注意事項
1. 為什麼我的 regex 在 grep 中不起作用?
許多使用者習慣使用 find 或 ls 的萬用字元(如 *、?),但這些在 regex 中有不同含義。在 regex 中,* 代表「前一個字符出現零次或多次」,而非「任意字符」。例如,grep 'a*' 會匹配包含任意數量 a 的行,甚至空行。
此外,括號的用法也易混淆。基礎 regex 使用 \( 和 \),而擴充 regex(-E)直接使用 ( 和 )。若未加 -E 卻使用 (,grep 會將其視為普通字符處理,導致匹配失敗。
2. 如何避免特殊字符的干擾?
當需要匹配的文本包含 regex 特殊字符(如 ., *, ?, [)時,必須進行「跳脫」(Escape)。例如,要匹配字串 file.txt,若直接使用 grep 'file.txt',它會匹配 file1txt、file-txt 等。正確做法是使用反斜線跳脫點號:
grep 'file\.txt' config.txt
或者,若確定是固定字串而非模式,可使用 grep -F 選項,將輸入視為純文字而非 regex,這能大幅提升效能並避免語法錯誤:
grep -F 'file.txt' config.txt
小結
正規表示式是 Linux 系統管理員的必備技能。透過理解 ^、$、.、[] 等核心符號,並熟練運用 grep -E 進行擴充匹配,我們能高效地處理複雜的文字數據。建議初學者從簡單的檔案過濾開始練習,逐步挑戰更複雜的日誌分析任務。記住,regex 的學習曲線雖陡,但一旦掌握,其帶來的效率提升將是無可估量的。