正規表示式 regex 速成指南 文章首圖

正規表示式 regex 速成指南

正規表示式 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/syslogjournalctl 輸出中篩選特定錯誤。假設我們想找出所有包含 errorError 且行首帶有時間戳記的記錄。

首先,建立一個模擬日誌檔 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 中不起作用?

許多使用者習慣使用 findls 的萬用字元(如 *?),但這些在 regex 中有不同含義。在 regex 中,* 代表「前一個字符出現零次或多次」,而非「任意字符」。例如,grep 'a*' 會匹配包含任意數量 a 的行,甚至空行。

此外,括號的用法也易混淆。基礎 regex 使用 \(\),而擴充 regex(-E)直接使用 ()。若未加 -E 卻使用 (grep 會將其視為普通字符處理,導致匹配失敗。

2. 如何避免特殊字符的干擾?

當需要匹配的文本包含 regex 特殊字符(如 ., *, ?, [)時,必須進行「跳脫」(Escape)。例如,要匹配字串 file.txt,若直接使用 grep 'file.txt',它會匹配 file1txtfile-txt 等。正確做法是使用反斜線跳脫點號:

grep 'file\.txt' config.txt

或者,若確定是固定字串而非模式,可使用 grep -F 選項,將輸入視為純文字而非 regex,這能大幅提升效能並避免語法錯誤:

grep -F 'file.txt' config.txt

小結

正規表示式是 Linux 系統管理員的必備技能。透過理解 ^$.[] 等核心符號,並熟練運用 grep -E 進行擴充匹配,我們能高效地處理複雜的文字數據。建議初學者從簡單的檔案過濾開始練習,逐步挑戰更複雜的日誌分析任務。記住,regex 的學習曲線雖陡,但一旦掌握,其帶來的效率提升將是無可估量的。