我試圖了解正則表達式在命令(^[0-9]..[a-zA-Z ]+$)
中檢測到的表達式(Linux 終端)grep
我知道如果我寫以下命令:
grep ^[0-9]..[a-zA-Z] filename.txt
我將檢測任何包含表達式的行,例如92afg
但我不確定這是什麼+$
意思以及我能夠使用命令檢測到什麼樣的表達式
grep ^[0-9]..[a-zA-Z]+$ filename.txt
我嘗試打開一個新的文本文件,然後只鍵入我認為會被檢測到的表達式,但它們都不匹配,所以我希望對此進行解釋。
答案1
讓我們來分解一下。首先,請注意此正規表示式使用“擴展正規表示式”語法 (ERE) -+
是一個元字符,在預設使用的“基本正則表達式”語法中不起作用grep
(意味著它會匹配自身並需要在該位置使用文字+
),因此如果您想使用該正則表達式grep
,您將需要傳遞該-E
選項。
- 是
^
一個錨點,將正規表示式的這個位置與行的開頭連結起來。 - 是
[0-9]
一個字元列表,將匹配屬於和之間排序範圍的任何單個(1)字元。具體包括什麼取決於“排序順序”,其中由環境變數決定。0
9
LC_COLLATE
- 匹配
.
任何單個字符,因此 2..
表示“任意兩個字符”。 - 返回
[a-zA-Z]
是一個字元列表,將匹配位於和之間的字元(1),以及位於和之間的字元。同樣,這意味著什麼取決於整理順序!a
z
A
Z
- 意思
+
是“之前的一個或多個” - 是
$
一個錨點,將正規表示式的這個位置連接到行尾。
所以,你的正規表示式旨在(1)符合任何符合以下條件的行
- 以任意數字開頭
- 後面接任兩個字符
- 並且只包含字母(但至少一個)直到行尾。
(1)關於它實際上可能做什麼,請參見下文
一些筆記
在您的範例中,您使用不含引號的正規表示式。這意味著任何字元在傳遞給命令之前都可以由 shell 解釋
grep
。如果您的模式包含$
或通配字元(*
、?
和[...]
字元清單!),shell 可能會嘗試執行變數擴充(從而取代正規表示式的部分內容)或將通配模式擴展為可能的多個檔案名,以便最終您將擁有更多參數在您最初想要的命令列上。 shell 特有的其他字元(>
、#
等;
)可能會導致更意外的行為。你應該使用grep -E '^[0-9]..[a-zA-Z]+$' filename.txt
反而。請注意,您可以透過使用該
-x
標誌強制「整行」匹配來擺脫開始和結束錨點:grep -x -E '[0-9]..[a-zA-Z]+' filename.txt
包含範圍(例如
a-z
)的字元清單是危險的因為他們可能不會給你你的想法。天真的人們可能會期望它們匹配 ASCII 表中起始字符和結束字符之間的所有字符,但這僅適用於C
區域設定。在其他語言環境中(特別是在通常設定的系統語言環境中,例如en_US.UTF-8
),排序規則類似於aAbB ... zZ
這樣,a-z
也將匹配大多數大寫字母。此外,匹配實際上不是在單一字元的層級上,而是在「排序規則元素」層級上,這意味著在某些語言環境中,甚至幾個字母的組合可能匹配(例如dzs
匈牙利語)!看這個答案(或者,一般來說,@Stéphane Chazelas 關於模式匹配的大多數答案)以獲得更多見解。如果您想確保範圍有效,請至少透過以下方式設定給定命令的排序規則LC_COLLATE="C" grep -E ' ... ' filename.txt
答案2
+
代表“前一個或多個重複”,$
是“行尾”。請注意與 with 的區別,*
意思是「零次或多次重複」。
所以它基本上意味著:任何以數字開頭的行,後面跟著任何類型的兩個字符,然後是一個或多個(可能是大寫)字母1,直到該行結束。
(請注意,某些語言環境可能不僅包含您期望的 AZ 或 az 中的 26 個字母,例如è
或ŷ
取決於語言)
有關正則表達式的良好指南,我強烈建議格里莫爾的美麗網站,我也衷心推薦例如sed
和awk
。
為什麼不匹配?
+
是擴展正規表示式的一部分(否則被解釋為文字+
- 符號)。
因此,要用作+
“一次或多次重複”,請使用-E
- 標誌grep
並引用正則表達式,以避免 shell 特殊字元出現任何問題:
grep -E '^[0-9]..[a-zA-Z]+$' filename.txt