【问题标题】:Can't understand this awk regex无法理解这个 awk 正则表达式
【发布时间】:2017-08-08 16:49:10
【问题描述】:

我试图理解 Unix 演讲中的特定代码行,但似乎无法理解 awk 部分在做什么。

整行是:man ls | col -b | grep '^[[:space:]]*ls \[' | awk -F '[][]' '{print $2}'。传递给 awk 的文本(如果由于某种原因您没有 man 程序)是:ls [-ABCFGHLOPRSTUW@abcdefghiklmnopqrstuwx1] [file ...]。不知何故,awk 能够将选项列表拉出到 ls,但我无法真正理解这个正则表达式 [][] 的实际工作原理以及它的匹配项。

我最好的猜测是外括号表示一个字符类,其内容包含][。如果是这样,为什么内括号不能写成[]。是不是因为一对括号[[]]在awk中有不同的含义?

提前致谢!

【问题讨论】:

    标签: regex bash awk


    【解决方案1】:

    在 POSIX 正则表达式中,[...] 称为 bracket expression

    它与其他 reegx 风格中的字符类非常相似。一个关键区别是反斜杠不是 POSIX 括号表达式中的元字符。

    如果您想在括号表达式中包含[],则需要正确放置,即] 位于开头,[

    根据链接的文章:

    要匹配],请将其作为开头[ 或否定^ 之后的第一个字符。要匹配 -,请将其放在结束 ] 之前。要匹配 ^,请将其放在最终文字 - 或结尾 ] 之前。

    在你的例子中:

    awk -F '[][]' '...'
    

    awk 将(输入)字段分隔符设置为单个文字 [] 字符。

    【讨论】:

      【解决方案2】:

      如果您有[[]],则意味着[ 在括号[] 中,例如[[] 后跟],因此字段分隔符将是[]

      $ echo a[]b | awk -F'[[]]' '{print $2}'
      b
      

      但是括号反过来:

      $ echo a][b | awk -F'[][]' '{print $3}'
      b
      

      现在$2 是空的,$3==b(天哪,做了什么)。

      【讨论】:

        【解决方案3】:

        您对字符类别的预感是正确的。如果您希望某些字符作为字段分隔符,那么您可以在括号中列出它们。使用 awk -F '[abc]' ... 将指定 a 和 b 和 c 字符作为分隔符。顺序无关紧要;您可以使用 awk -F '[cab]' ... 并获得相同的结果。

        但是,如果您希望分隔字符本身是左右括号呢?正则表达式的文档(在许多系统上为man re_format)是这样说的:

        To  include a literal `]' in the list, make it the first character ...
        

        考虑到表达式的解析方式,这是有道理的。当解析器扫描表达式时,它正在寻找结尾,右括号。它不关心看到另一个左括号或逗号或空格或其他什么,但右括号会标记结束,除非有某种方法告诉解析器从字面上理解它。由于括号之间没有任何内容,[] 是没有用的,作为第一个字符的右括号被定义为其他含义:这不能是结尾,所以请按字面意思理解这个右括号。

        因此,如果您希望括号作为字段分隔字符,则在括号之间列出 [],但您将右括号放在列表中的第一位,以便按照说明按字面意思理解:@987654328 @

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多