簡體   English   中英

使用帶有或不帶有引號的grep regex模式之間的區別?

[英]Difference between using grep regex pattern with or without quotes?

我正在從Linux Academy學習,該教程顯示了如何使用grep和regex。

他將正則表達式模式放在引號之間,如下所示:

grep 'pattern' file.txt

這似乎與不帶引號的情況相同:

grep pattern file.txt 

但是當他做這樣的事情時,他需要轉義{和}:

grep '^A\{1,4\}' file.txt 

在進行了一些測試之后,編寫沒有引號的模式時似乎不需要這些換碼符。

grep ^A{1,4} file.txt

那么這兩種方法有什么區別? 是否需要報價? 為什么在第一種情況下需要轉義字符?

最后,我還看到了其他方法,例如grep -E和egrep,這是人們使用正則表達式進行grep的最常用方法嗎?

編輯:感謝您提醒該模式在文件之前。

非常感謝!

有時您可以省略引號,但這是最安全的做法。 這是因為正則表達式的語法與文件名通配符模式的語法重疊,並且當外殼程序看到類似通配符模式的內容(並且不在引號中)時,外殼程序將嘗試將其“擴展”為匹配的文件名。 如果沒有匹配的文件,它將原樣傳遞,但是如果有匹配的文件,它將被匹配的文件名替換。

這是一個簡單的例子。 假設我們正在嘗試在file.txt中搜索“ a”,然后可選地加上一些“ b”,並僅打印匹配項。 因此,您運行:

grep -o ab* file.txt

現在,“ ab*可以解釋為通配符模式,查找以“ ab”開頭的文件,shell 以這種方式解釋它。如果當前目錄中沒有以“ ab”開頭的文件,則不會不會引起問題,但是假設有兩個“ abcd.txt”和“ abcdef.jpg”,然后shell將其擴展為以下內容:

grep -o abcd.txt abcdef.jpg file.txt

...然后grep將在文件abcdef.jpg和file.txt中搜索正則表達式模式abcd.txt

因此,基本上,使用不帶引號的正則表達式模式可能有效,但並不安全 所以不要這樣做。

順便說一句,我也建議您使用單引號而不是雙引號,因為即使某些正則表達式字符在雙引號中(多數為美元符號和反斜杠/轉義符),它們也會被外殼程序專門處理。 同樣,它們通常會通過不變的方式,但並非總是如此,除非您了解(有些混亂)解析規則,否則可能會得到意外的結果。

BTW ^ 2,出於類似的原因,您應該(幾乎)始終在變量引用周圍加上雙引號(例如grep -O 'ab* "$filename"而不是grep -O 'ab*' $filename )。 單引號根本不允許變量引用。 不帶引號的變量引用會受到單詞拆分和通配符擴展的影響,這兩者都可能引起麻煩。 用雙引號括起來的變量得到擴展,而沒有別的

順便說一句^ 3,有很多正則表達式語法的變體。 您需要避免在示例表達式中使用花括號的原因是,默認情況下, grep使用POSIX“基本”正則表達式語法(“ BRE”) 在BRE語法中,某些正則表達式特殊字符(包括大括號和括號)必須轉義以具有其特殊含義(而其他一些字符,如與|交替顯示則完全不可用)。 另一方面, grep -E使用“擴展的”正則表達式語法(“ ERE”),其中這些字符具有特殊的含義,除非對其進行轉義。

然后是Perl兼容語法(PCRE)和許多其他變體。 使用語法的錯誤變體是導致正則表達式出現問題的常見原因(例如,在ERE上下文中使用perl擴展名,如此此處 )。 重要的是要知道您使用的工具可以理解哪種變體,並將正則表達式編寫為該語法。

這是一個簡單的示例:“ a”,后跟1到3個類似空格的字符,后跟“ b”,這是各種正則表達式語法的變體:

a[[:space:]]\{1,3\}b    # BRE syntax
a[[:space:]]{1,3}b      # ERE syntax
a\s{1,3}b               # PCRE syntax

為了使事情變得更復雜,某些工具名義上將接受一種語法,但也允許其他語法變體的某些擴展。 在上面的示例中,您可以看到perl為空格字符添加了簡寫\\s ,這不是POSIX標准語法的一部分。 但是實際上,許多名義上使用BRE或ERE的工具實際上都會接受\\s簡寫。

實際上,在您的問題中轉義有兩個完全不相關的方面。 第一個必須要做的是如何在bash中表示字符串。 這與可讀性有關,通常意味着個人品味。 例如,我不喜歡轉義,因此我更喜歡將ab\\ cd寫為'ab cd' 因此,我會寫

echo 'ab cd'
grep -F 'ab cd' myfile.txt

代替

echo ab\ cd
grep -F ab\ cd myfile.txt

但任何一個都沒有錯,您可以選擇對您來說更簡單的一個。

其他方面確實給相關grep ,至少只要你不使用-Fgrep的選項,它總是解釋搜索參數字面上。 在這種情況下,不涉及外殼程序,問題是某個字符是解釋為正則表達式字符還是文字。 戈登·戴維森(Gordon Davisson)已經詳細解釋了這一點,因此我僅給出一個結合了兩個方面的示例:

假設您要grep一個空格,然后是一個或多個句點,然后是另一個空格。 你不能這樣寫

grep -E  .+  myfile.txt

因為這些空間會被bash和the . grep有特殊的意義。 因此,您必須選擇一些轉義機制。 我的個人風格是

grep -E ' [.]+ ' myfile.txt

但是許多人不喜歡[.] ,而是喜歡\\. 代替。 這將成為

grep -E ' \.+ ' myfile.txt

它仍然使用引號從外殼中搶救空格,但轉義了grep的時間。 如果您不想使用任何引號,可以編寫

grep -E \ \\.+\  myfile.txt

請注意,您需要前綴\\其意在通過另一個grep, \\ ,因為反斜杠,就像一個空間,為外殼特殊的意義,如果你不寫\\\\. ,grep不會看到反斜杠,而只是一個時期。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM