grep 指令的本質是什麼?

grep 指令的本質是什麼?

我想使用通配符“*”來 grep 所有 .txt 檔案。
我嘗試了這個命令(以及沒有引號“”)但失敗了。

ls | grep "*.txt"

有趣的是,如果我在 grep 命令中放入與目錄中的 .txt 檔案相對應的另一個字符,它就會起作用

>>ls | grep s*.txt
sample.txt

我知道這ls *.txt會起作用,但我對 grep 命令的性質有點驚訝。有人可以幫助我為什麼會發生這種情況嗎?

是不是因為grep使用了正規表示式,請幫忙。

答案1

在正規表示式中,*意味著“任意數量的前一項”,而不是“任意數量的任意字元”,就像在 shell 模式中那樣。並.表示“任何單一字元”。因此,要查找“任何內容,後跟文字.txt”,您可以使用.*\.txt.或者只是\.txt,因為通常正規表示式匹配會在行中的任何位置搜尋匹配項。然後,\.txt也會符合類似 的檔名foo.txtgz,因為.txt不必位於最後。您需要\.txt$將模式鎖定到行尾。

正規表示*.txt式要么是無意義的、是錯誤的,要么是查找字面星號,具體取決於實現以及您使用的是基本正則表達式 ( grep) 還是擴展正則表達式 ( grep -E)。最好不要使用它。

另一方面,s*.txt會尋找“任意數量的字母s,然後是任意單個字符,然後是文字txt”。這是一個更有效的正規表示式,但是...仍然不匹配sample.txt

相反,第二個命令中發生的情況是,由於s*.txt未加引號,shell 會在看到它s*.txt之前展開grep它。如果唯一符合的檔案是sample.txt,則grep在 的輸出中尋找該檔案ls。 (如果有多個匹配的檔案名,第一個將被視為模式,其餘的將作為檔案名稱進行grep讀取。在這種情況下,它將忽略來自管道的輸入。)


但是,ls也可以獲得文件列表,因此雖然您可以使用

ls | grep '\.txt'

要取得任何.txt文件,使用它可能會更容易

ls *.txt 

反而。

答案2

部分原因是因為grep使用了正規表示式(事實上,這就是re名稱中的代表的意思 - 它是G局部的r規則的e表達p列印).

正規表示式中的通配符與shell 通配符中的通配符*不同。*

在正規表示式中,*表示「零個或多個先前定義的物件」。然而,.通配符,意思是「一個字元」。

在 shell glob 中,*表示「零個或多個字元」。 .根本不是通配符。

當您grep查找模式時"*.txt",您正在尋找零個或多個任何內容,後面跟著一個字符,最後是文字字串txt

當您grep使用模式"s*.txt"m you are looking for a literals , followed by zero or mores s, followed by any character, followed by the literal stringtxt`.

這就是為什麼您在正規表示式中會發現的一個常見現像是.*,這意味著「任何字元之一後跟零個或多個任何字元」。正規表示式「實際上是除零字元之外的任何字元組合」。

當您ls *.txt告訴 shell「尋找與 glob 模式相符的任何檔案名稱」時*.txt,請在此處列出它們,並將它們作為參數提供給ls命令。

答案3

請注意 grep 正在搜尋文件內容第一個參數是搜尋模式,其他參數解釋為要查看的文件

grep -H -o當使用標誌或將您的腳本放入grep腳本並運行它以bash -x script查看 shell glob 在作為參數傳遞之前如何擴展時,您會變得更加清楚

相關內容