簡體   English   中英

為什么在同一文件中'grep“ * .h”'和'grep -E“ * .h”'的不同輸出

[英]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.

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