![](/img/trans.png)
[英]Why does grep show me different output depending on my input file size?
[英]why different output of ' grep “*.h” ' and ' grep -E “*.h” ' on the same file
假設文件內容如下:
abc.h hello world
grep "*.h" file
的輸出和grep -E "*.h" file
的輸出不同。 據我了解,它們應該是相同的。 *
是正則表達式元字符。 輸出都應該是abc.h
輸出與
grep "*.h" file # ==> No output
grep -E "*.h" file # ==> abc.h
請幫助澄清這個問題!
*.h
不應與任何一行匹配。 如果是這樣,那是因為您的特定grep的擴展正則表達式引擎處理邊界或量詞的方式有所不同。 您可能會在GNU grep中看到這種奇怪的行為,但是BSD grep正確地報告了grep: repetition-operator operand invalid
。
您可能的意思是.*h
,無論您使用BRE還是ERE引擎,它都將匹配這兩行。 如果只想匹配提供的語料庫中的abc.h
,則需要:
grep '\.h' /tmp/foo
這將匹配任何帶有字母句點后跟字母h
。 您甚至可能希望將其錨定在該行的末尾,以確保您不會誤捕獲foo abc.h bar
類的文本。 例如:
grep '\.h$' /tmp/foo
POSIX定義(POSIX) 正則表達式的行為,並定義基本正則表達式(BRE)和擴展正則表達式(ERE)。 使用grep -E
需要ERE; 沒有-E
,您將獲得BRE(使用-F
您將不會獲得正則表達式)。
BRE中*
的POSIX定義是:
*
除使用時,<asterisk>
應該是特殊的:
在方括號中
作為整個BRE的第一個字符(在首字母“ ^”之后,如果有的話)
ERE中*
的POSIX定義表示:
*+?{
除了在方括號表達式中使用時,<asterisk>
,<plus-sign>
,<question-mark>
和<left-brace>
應該是特殊的(請參閱RE方括號表達式)。 以下任何一種用途都會產生不確定的結果:
- 如果這些字符首先出現在ERE中,或者緊接在
<vertical-line>
,<circumflex>
或<left-parenthesis>
在問題中:
使用grep '*.h'
使用的是BRE, *
首先出現*
所以它不是特殊字符; 它與*
匹配,后跟任意字符,后跟h
。
This would be matched *Zh because the * and the h are separated by one character This would not be matched because the * and the h are not separated by one character
使用grep -E '*.h'
調用未定義的行為。 任何結果都是有效的。
為了可靠地匹配abc.h
和其他以.h
結尾的字母數字文件名,您可以使用類似以下的方法:
grep '[[:alnum:]]\.h'
在這種情況下,無需特別使用*
; 如果這樣做,則可以編寫以下其中一項:
grep '^[[:alnum:]][[:alnum:]]*\.h$'
grep '^[[:alnum:]]\{1,\}\.h$'
它們查找由一個或多個字母數字組成的行,然后是.
和h
和行尾。 如果您不喜歡字符類表達式符號( [:alnum:]
部分),則可以這樣編寫:
grep '^[a-zA-Z0-9][a-zA-Z0-9]*\.h$'
grep '^[a-zA-Z0-9]\{1,\}\.h$'
如果願意,可以添加下划線:
grep '^[[:alnum:]_][[:alnum:]_]*\.h$'
grep '^[a-zA-Z0-9_][a-zA-Z0-9_]*\.h$'
您可以使用擴展的正則表達式,例如:
grep '^[[:alnum:]_]+\.h$'
grep '^[a-zA-Z0-9_]+\.h$'
Etcetera。 選項眾多!
-E
擴展的正則表達式,其中*
表示前一項將被匹配零次或多次
-G
(默認)-基本正則表達式,其中*
表示*
字符
-P
-Perl正則表達式,其中*
含義與-E
的相同,但是*.h
無法編譯,因為沒有重復的內容( *
之前沒有字符)。 使用libpcre
:
ldd /bin/grep
linux-vdso.so.1 (0x00007ffefddd4000)
libpcre.so.1 => /lib64/libpcre.so.1 (0x0000003bd8a00000)
libc.so.6 => /lib64/libc.so.6 (0x0000003bd6a00000)
libpthread.so.0 => /lib64/libpthread.so.0 (0x0000003bd7200000)
/lib64/ld-linux-x86-64.so.2 (0x0000003bd6600000)
因此, grep -E "*.h"
將匹配任何具有.h
序列的字符串; grep -G "*.h"
將匹配任何具有*.h
序列的字符串; grep -P "*.h"
將無法編譯。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.