【问题标题】:Why does this sed command output "[18" instead of "18"?为什么这个 sed 命令输出“[18”而不是“18”?
【发布时间】:2024-01-19 13:38:01
【问题描述】:
echo [18%] | sed s:[\[%\]]::g

我对此感到非常困惑,因为相同的模式成功地替换了 vim 中的 [18%]。我还在一些在线正则表达式工具中测试了该表达式,他们都说它将按预期匹配[%]。我尝试添加 -r 选项以及将替换命令括在引号中。

我知道我可以使用其他命令来完成此任务,但我想知道它为什么会这样,以便更好地了解 sed。

【问题讨论】:

    标签: regex unix sed string-substitution


    【解决方案1】:
    $ echo [18%] | sed s:[][%]::g
    18
    

    sed 支持 POSIX.2 正则表达式语法:默认为基本 (BRE) 语法,带有 -r 标志的扩展语法。在基本或扩展的 POSIX.2 语法中,您可以通过将右方括号设为字符类中的第一个字符来包含它。反斜杠没有帮助。

    这很烦人,因为几乎所有其他现代语言和工具都使用 Perl 或类似 Perl 的正则表达式语法。 POSIX 语法是不合时宜的。

    您可以在 regex(7) 手册页中了解 POSIX.2 语法。

     A bracket expression is a list of  characters  enclosed  in  "[]".   It  normally
     matches  any  single character from the list (but see below).  If the list begins
     with '^', it matches any single character (but see below) not from  the  rest  of
     the  list.  If two characters in the list are separated by '-', this is shorthand
     for the full range of characters between those two (inclusive) in  the  collating
     sequence,  for  example, "[0-9]" in ASCII matches any decimal digit.  It is ille‐
     gal(!) for two ranges to share an endpoint, for  example,  "a-c-e".   Ranges  are
     very  collating-sequence-dependent, and portable programs should avoid relying on
     them.
    
     To include a literal ']' in the list, make it the first  character  (following  a
     possible '^').  To include a literal '-', make it the first or last character, or
     the second endpoint of a range.  To use a literal '-' as the first endpoint of  a
     range,  enclose  it in "[." and ".]"  to make it a collating element (see below).
     With the exception of these and some  combinations  using  '['  (see  next  para‐
     graphs), all other special characters, including '\', lose their special signifi‐
     cance within a bracket expression.
    

    【讨论】:

    • 感谢您的解释。但是,-r 选项不应该通过指示 sed 使用扩展的正则表达式来解决这个问题吗?顺便说一句,我在 linux 机器上使用 bash。
    • 在括号表达式中包含 ] 的方式对于 BRE 和 ERE 都是相同的(即使其成为第一个字符),因此使用 -r 或不使用没有区别。
    • 引用的文字适用于这两个品种。特别参见最后一句话:“...所有其他特殊字符,包括 '\',在括号表达式中失去其特殊意义。”不幸的是,-r 并没有改变这一点。
    • 好吧,这很有道理。谢谢大家!