【问题标题】:Grep does not show results, online regex tester doesGrep 不显示结果,在线正则表达式测试器显示
【发布时间】:2019-04-18 02:18:43
【问题描述】:

我对 grep 的行为相当陌生。我有一堆包含如下行的 XML 文件:

<identifier type="abc">abc:def.ghi/g1234.ab012345</identifier>
<identifier type="abc">abc:def.ghi/g5678m.ab678901</identifier>

我想在斜线之后获取标识符部分并使用RegexPal构造一个正则表达式:

[a-z]\d{4}[a-z]*\.[a-z]*\d*

它突出了我想要的一切。完美的。现在,当我在同一个文件上运行 grep 时,我没有得到任何结果。而且正如我所说,我对 grep 真的不太了解,所以我尝试了所有不同的组合。

grep [a-z]\d{4}[a-z]*\.[a-z]*\d* test.xml
grep "[a-z]\d{4}[a-z]*\.[a-z]*\d*" test.xml
egrep "[a-z]\d{4}[a-z]*\.[a-z]*\d*" test.xml
grep '[a-z]\d{4}[a-z]*\.[a-z]*\d*' test.xml
grep -E '[a-z]\d{4}[a-z]*\.[a-z]*\d*' test.xml

我做错了什么?

【问题讨论】:

    标签: regex grep


    【解决方案1】:

    您的正则表达式与输入不匹配。让我们分解一下:

    • [a-z] 匹配 g
    • \d{4} 匹配 1234
    • [a-z]* 不匹配 .

    另外,我相信grep 和家人不喜欢\d 语法。试试[0-9][:digit:]

    最后,在使用正则表达式时,更喜欢egrep 而不是grep。我不记得确切的细节,但egrep 支持更多的正则表达式运算符。此外,在许多 shell 中(包括您提到的 OS X 上的 bash,使用单引号而不是双引号,否则 * 将在 grep 看到它之前被 shell 扩展为当前目录中的文件列表(以及其他 shell元字符也会被扩展)。Bash 不会触及单引号中的任何内容。

    【讨论】:

    • 这里有错字,抱歉。现在已经更正了。并且在线工具中的正则表达式仍然匹配。
    • 非常感谢! [0-9] 提供了帮助。
    • 非常感谢! egrep 岩石。
    • 我很困惑。 [a-z]* 不匹配 . 但它是可选的,因此它匹配 0 个字符,然后正则表达式的下一位匹配点。这就是它在正则表达式测试器站点上工作的原因。我认为实际的问题是像你建议的那样使用扩展的正则表达式。
    【解决方案2】:

    grep 默认不支持\d。要匹配数字,请使用[0-9],或允许与 Perl 兼容的正则表达式:

    $ grep -P "[a-z]\d{4}[a-z]*\.[a-z]*\d*" test.xml
    

    或:

    $ egrep "[a-z][0-9]{4}[a-z]*\.[a-z]*[0-9]*" test.xml
    

    【讨论】:

      【解决方案3】:

      grep 使用“基本”正则表达式:(摘自手册页)

      Basic vs Extended Regular Expressions
         In basic regular expressions the meta-characters ?, +, {, |, (, and ) lose their
         special meaning; instead use the backslashed versions \?, \+, \{,  \|,  \(,  and
         \).
      
         Traditional  egrep  did  not  support  the  {  meta-character,  and  some  egrep
         implementations support \{ instead,  so  portable  scripts  should  avoid  {  in
         grep -E patterns and should use [{] to match a literal {.
      
         GNU  grep -E  attempts  to  support  traditional usage by assuming that { is not
         special if it would be the start of  an  invalid  interval  specification.   For
         example,  the  command  grep -E '{1'  searches  for  the two-character string {1
         instead of reporting a syntax error in the regular expression.   POSIX.2  allows
         this behavior as an extension, but portable scripts should avoid it.
      

      另外,取决于您在哪个 shell 中执行的 '*' 字符可能会被扩展。

      【讨论】:

      • 我在 OS X 上使用 bash 3.2。-E 开关也无济于事(在我原来的问题中添加)
      【解决方案4】:

      您可以使用以下命令:

      $ cat file
      <identifier type="abc">abc:def.ghi/g1234.ab012345</identifier>
      
      # Use -P option to enable Perl style regex \d.
      $ grep -P  '[a-z]\d{4}[a-z]*\.[a-z]*\d*' file
      <identifier type="abc">abc:def.ghi/g1234.ab012345</identifier>
      
      # to get only the part of the input that matches use -o option:
      $ grep -P -o '[a-z]\d{4}[a-z]*\.[a-z]*\d*' file
      g1234.ab012345
      
      # You can use [0-9] inplace of \d and use -E option.
      $ grep -E -o '[a-z][0-9]{4}[a-z]*\.[a-z]*[0-9]*' file
      g1234.ab012345
      $ 
      

      【讨论】:

      • 对不起,我有一个错字。测试文件是对的,在线工具中正则匹配。
      【解决方案5】:

      试试这个:

      [a-z]\d{5}[.][a-z]{2}\d{6}

      【讨论】:

      • 好的,改变需求,然后试试这个:[a-z][0-9]{4}[1-z]*[.][a-z]{2}[0-9]{ 6}
      【解决方案6】:

      在 grep 中试试这个表达式:

      [a-z]\d{4}[a-z]*\.[a-z]*\d*
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-12-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-06-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多