sed 命令适用于 e 标志但不适用于 E

Prv*_*dav 2 sed regular-expression

我有一个字符串,我需要#在开头添加, 即转换[ -n "$ID" -a "$ID" -le 200 ] && return#[ -n "$ID" -a "$ID" -le 200 ] && return. 我可以使用以下命令:

echo '[ -n "$ID" -a "$ID" -le 200 ] && return'| sed -n -e 's/\[ -n "$ID" -a "$ID" -le 200 \] && return/#&/p'
Run Code Online (Sandbox Code Playgroud)

有用。现在我有两个问题,关于E, flag。

  1. 对于 string [ -n "$ID" -a "$ID" -le 200 ],如果我转义括号,则不起作用;但是,当我不逃避它们时它会起作用,即

    sed -n -E 's/[ -n "$ID" -a "$ID" -le 200 ]/#&/p'
    
    Run Code Online (Sandbox Code Playgroud)

    工作时

     sed -n -E 's/\[ -n "$ID" -a "$ID" -le 200 \]/#&/p'
    
    Run Code Online (Sandbox Code Playgroud)

    不起作用。

  2. 对于完整的字符串[ -n "$ID" -a "$ID" -le 200 ] && return,当我不转义它们时,它给了我错误的答案:

    echo '[ -n "$ID" -a "$ID" -le 200 ] && return'| sed -n -E 's/[ -n "$ID" -a "$ID" -le 200 ] && return/#&/p'
    
    Run Code Online (Sandbox Code Playgroud)

    它给了我输出:

     [ -n "$ID" -a "$ID" -le 200 #] && return
    
    Run Code Online (Sandbox Code Playgroud)

我想知道它是如何工作的。

Phi*_*pos 5

sed -n -E 's/[ -n "$ID" -a "$ID" -le 200 ]/#&/p'
Run Code Online (Sandbox Code Playgroud)

不像你期望的那样工作,这更像是一个巧合:[...]是一组匹配的字符。在该集合中,您有一个-n从空格 (0x20) 到n(0x6E) 的范围,其中可以包括[(0x5B),具体取决于您的区域设置。所以集合匹配第一个字符。看看当你#&___作为替代品时会发生什么......我猜不是你的意图?

这就是你的完整案例失败的原因:集合的匹配字符是]因为它后面是模式的其余部分,这就是为什么#插入那里。

扩展正则表达式的问题就像@steeldriver 假设:$锚定模式:

括号表达式外的 ( '$' ) 应将其结尾的表达式或子表达式锚定到字符串的末尾;这样的表达式或子表达式只能匹配以字符串最后一个字符结尾的序列。例如,ERE“ef$”和“(ef$)”匹配字符串“abcdef”中的“ef”,但在字符串“cdefab”中匹配失败,ERE“e$f”有效,但永远无法匹配,因为 'f' 阻止表达式“e$”匹配以最后一个字符结尾。

所以在 ERE 中,$需要对文字进行转义,而在 BRE 中,仅当它是模式的最后一个字符时才需要转义。

另请注意,-e将下一个参数标记为脚本,如果只有一个脚本,则-E是可选的,而是开关。删除-e“-E”仅在只有一个脚本时才有效,因为无论如何它都是多余的。