什麼表達式可以符合 grep 指令中的模式 (^[0-9]..[a-zA-Z ]+$)? Linux bash

什麼表達式可以符合 grep 指令中的模式 (^[0-9]..[a-zA-Z ]+$)? Linux bash

我試圖了解正則表達式在命令(^[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)字元。具體包括什麼取決於“排序順序”,其中由環境變數決定。09LC_COLLATE
  • 匹配.任何單個字符,因此 2..表示“任意兩個字符”。
  • 返回[a-zA-Z]是一個字元列表,將匹配位於和之間的字元(1),以及位於和之間的字元。同樣,這意味著什麼取決於整理順序!azAZ
  • 意思+是“之前的一個或多個”
  • $一個錨點,將正規表示式的這個位置連接到行尾。

所以,你的正規表示式旨在(1)符合任何符合以下條件的行

  • 以任意數字開頭
  • 後面接任兩個字符
  • 並且只包含字母(但至少一個)直到行尾。

(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
    
  2. 包含範圍(例如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 個字母,例如èŷ取決於語言)

有關正則表達式的良好指南,我強烈建議格里莫爾的美麗網站,我也衷心推薦例如sedawk


為什麼不匹配?

+是擴展正規表示式的一部分(否則被解釋為文字+- 符號)。

因此,要用作+“一次或多次重複”,請使用-E- 標誌grep並引用正則表達式,以避免 shell 特殊字元出現任何問題:

grep -E '^[0-9]..[a-zA-Z]+$' filename.txt

相關內容