
我有一個包含以下內容的文件:
sh-4.2$ cat file1
example of multiple
pattern
this is an
example of multipole
sorry multiple
pattern matching
using grep
so the example is the
file itself
-example
-multiple
-bye
tata
!
在上述文件中搜尋“-example”時,grep 指令沒有給出所需的輸出。我知道如果模式包含“-”,則應使用 -e 選項:
在第一個例子中我使用了-例子直接不帶任何引號:
sh-4.2$ grep -example file1
example of multiple
example of multipole
so the example is the
-example
-例子附單引號:
sh-4.2$ grep '-example' file1
example of multiple
example of multipole
so the example is the
-example
-例子帶有雙引號和轉義字符
sh-4.2$ grep "\-example" file1
-example
sh-4.2$
答案1
好吧,您知道搜尋模式包含“-”,並且您知道當搜尋模式包含“-”時,您需要使用該-e
標誌。由於您沒有使用該-e
標誌,因此 shell 會將您的「模式」解釋為參數(和參數)。您可以透過以下方式查看:
$ grep "-foo" file1
grep: oo: No such file or directory
透過擴展,您的程式碼grep "-example" file1
告訴 shell 您想要grep
使用-e
參數和參數“xample”運行。
這與我們嘗試類似的方法時遇到的問題相同rm -my-silly-file-name
- 它不起作用,我們需要使用類似的方法rm ./-my-silly-file-name
。另一種解決方法是rm -- -my-silly-file-name
.我們可以在這裡使用這個慣用語:
$ grep -- "-example" < file1
-example
「--」告訴 shell 它後面的所有內容不是一個論點。
或者,您可以簡單地用“\”轉義“-”,如您所見:
grep "\-example" file1
本文詳細介紹了引用的一些細節: 相關部分是應由 shell 解釋的參數和反引號指令用雙引號括起來。當您使用雙引號時,內容由 shell 解釋。
答案2
您“知道模式[以]'-'開頭,則應使用-e選項”,但您在應該使用它時卻沒有使用它。grep -e -example file1
會給你預期的結果。
以下是每個範例中實際執行的內容:
grep -example file1
=>grep -e xample file1
(-e是必要的)grep '-example' file1
=>grep -e xample file1
(-e是必要的)grep "\-example" file1
=>grep \-example file1
(-e不是必需的)
答案3
以 開頭的參數-
被視為一個選項。
在前兩種情況下,傳遞給的第一個參數grep
是-example
,它grep
理解為-e xample
(選項xample
的參數-e
,因此搜尋xample
)。
在第三種情況\-example
下傳遞給grep
.由於它不以 開頭-
,因此不將其視為選項。它被視為正規表示式。然而,根據 POSIX 未指定 的行為\-
,因此您無法保證它相符的內容。對於大多數grep
實現,\-
將匹配 a -
,但是您可以想像可能是特殊運算符grep
的實現\-
(例如,請參閱 GNUgrep
其中\+
是特殊運算符並且與文字不符+
)。
如果您-example
不想被視為一種選擇,您需要:
grep -- -example file
。標誌著--
選項的結束。它後面的任何內容都是非選項(因此第一個參數是要搜尋的模式,其餘是要尋找的檔案清單)。grep -e -example file
。這裡,-example
被視為-e
選項的參數。
這就是為什麼你應該習慣寫作的原因:
grep -e "$pattern" file
或者
grep -- "$pattern" file
如果你不能保證$pattern
不會開始-
。
注意,這裡你也可以這樣寫:
grep '[-]example' file
雖然看到括號表達式(不含範圍)與 bash 中的意外字元相符關於這種方法可能出現的併發症。