處理 grep 模式中空格的正確方法
最新的grep 3.8對使用反斜杠轉義空格的模式發出警告
$ grep "bla\ bazz" t /tmp/bin/grep: warning: stray \ before white space ...
而 grep 3.6 沒有抱怨。處理這種模式的正確方法是什麼?只是不逃離空間?IE
$ grep "bla bazz" t
是否有一些更奇特
grep
的 ’s 會錯誤地處理未轉義的空間?也許,要使用不同的配額來使它變得乾淨整潔?
您只需要轉義一個空格以保護它免受外殼的影響,而不是
grep
. 空格字元對於正則表達式不是特殊的,它們僅在 shell 中是特殊的,因為它們是 shell 用來定義參數的。因此,如果您的模式未引用(這是一個壞主意),則需要空格:$ echo 'foo bar' | grep -c foo\ bar 1
這確保 she shell 不會解析
foo bar
為兩個參數,將 .bar
作為文件名傳遞給grep
. 您可以通過以下方式看到這一點set -x
:$ set -x $ echo 'foo bar' | grep -c foo\ bar + grep -c 'foo bar' + echo 'foo bar' 1
如果你不逃跑,你會得到:
$ echo 'foo bar' | grep -c foo bar + grep -c foo bar + echo 'foo bar' grep: bar: No such file or directory
但是,如果您引用您的模式,這將保護它免受外殼程序的影響,並且不需要轉義:
$ echo 'foo bar' | grep -c "foo bar" + grep --color -c 'foo bar' + echo 'foo bar' 1
或者
$ echo 'foo bar' | grep -c 'foo bar' + grep --color -c 'foo bar' + echo 'foo bar' 1
這就是為什麼
grep
現在當它在空格前看到文字(引用)\
時會警告您:它警告您\
只是變成(空格),因為沒有什麼可以逃脫,因此\
沒有意義。當它不是“可轉義”時,它會對任何其他被轉義的字元執行相同的操作:$ echo 'foo bar' | grep -c "f\oo\ bar" + grep --color -c 'f\oo\ bar' + echo 'foo bar' grep: warning: stray \ before o grep: warning: stray \ before white space 1
正則表達式中不特殊的空格字元(啟用標誌
perl
時的 -like除外x
),因此不得轉義。\
後跟空格會在 POSIX 正則表達式中產生未指定的結果。所以你要:
grep 'blah bazz'
如果你想讓它更明顯,你可以使用:
grep 'blah[ ]bazz'
更一般地,您不應該將
\
is 放在不是正則表達式運算符的字元的前面。WhereX
is not a 正則表達式運算符,\X
很可能是,如果不是現在,也許在未來的版本中。例如,+
,<
,d
不是基本的正則表達式操作符,但是\<
,\+
和\d
用於某些grep
實現。您可能希望在
\
後面使用空格:grep -P '(?x) foo \ bar'
perl -ne 'print if / foo \ bar /x'
在標誌打開
foo bar
時匹配。x
但即使在那裡,你寧願這樣做:grep -P '(?x) foo [ ] bar'
使其更易讀。該
x
標誌的全部意義在於使正則表達式更清晰,例如:perl -ne 'print if m{ \d{4} # year - \d{2} # month - \d{2} # day [ ] (foo | bar | baz)}x'
對比
perl -ne'print if/\d{4}-\d{2}-\d{2} (foo|bar|baz)/'
但是,您不能
[ ]
與xx
標誌一起使用(在 perl 5.26+ 中,而不是 PCRE),其中括號表達式中的空格也會被忽略。有關
perldoc perlre
perl 正則表達式的詳細資訊,以及man pcrepattern
PCRE(perl 兼容的正則表達式)的詳細資訊,請參閱。使用\Q \E
是另一種選擇。在任何情況下,雖然空格是 shell 語法中的特殊字元而不是正則表達式中的特殊字元,但有許多字元在兩者中都是特殊的,例如
*
,\
,(
,)
,?
,$
,^
,[
,]
, 所以需要轉義對於兩者,如果要按字面意思匹配,最好使用 shell 的引號,以及正則表達式的\
(或[...]
,或\Q...\E
類似 perl 的)。由於
\
和$
在正則表達式中很常見,而且這些字元在雙引號內對 shell 來說仍然是特殊的,因此將正則表達式放在單引號而不是雙引號中是一個好習慣。如果您需要將 shell 參數擴展為正則表達式,grep "^$var"
或者需要在正則表達式中包含 a ,則只能使用雙引號'
。要
grep
文字字元串而不是正則表達式,或者換句話說,要轉義每個正則表達式運算符,您可以使用-F
(forF
ixed string) 選項來grep
. 例如:grep -F 'blah\ bazz'
會尋找包含
blah\ bazz
.