我有一个字符串,我需要#
在开头添加 , ,即转换[ -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'
有用。现在我有两个问题,关于E
flag。
对于字符串
[ -n "$ID" -a "$ID" -le 200 ]
,如果我转义括号,则不起作用;但是,当我不逃避它们时它会起作用,即sed -n -E 's/[ -n "$ID" -a "$ID" -le 200 ]/#&/p'
工作同时
sed -n -E 's/\[ -n "$ID" -a "$ID" -le 200 \]/#&/p'
不起作用。
对于完整的 string
[ -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'
它给了我输出:
[ -n "$ID" -a "$ID" -le 200 #] && return
我想知道它是如何运作的。
答案1
sed -n -E 's/[ -n "$ID" -a "$ID" -le 200 ]/#&/p'
不按照您期望的方式工作,这更多的是巧合:[...]
是匹配的字符的集合。在该集合中,范围-n
从空白 (0x20) 到n
(0x6E),其中可以包括[
(0x5B),具体取决于您的区域设置。所以该集合与第一个字符匹配。看看当你#&___
作为替代品时会发生什么......我猜这不是你的意图?
这就是整个案例失败的原因:集合的匹配字符是 the,]
因为它后面跟着模式的其余部分,这就是将 the#
插入那里的原因。
扩展正则表达式的问题就像 @steeldriver 假设的那样:$
锚定模式:
括号表达式之外的 ( '$' ) 会将其结尾的表达式或子表达式锚定到字符串的末尾;这样的表达式或子表达式只能匹配以字符串的最后一个字符结尾的序列。例如,ERE“ef$”和“(ef$)”匹配字符串“abcdef”中的“ef”,但在字符串“cdefab”中匹配失败,并且ERE“e$f”有效,但是永远无法匹配,因为“f”阻止表达式“e$”匹配以最后一个字符结尾的内容。
因此,在 ERE 中,文字$
需要转义,而在 BRE 中,仅当它是模式的最后一个字符时才需要转义。
另请注意,-e
将下一个参数标记为脚本,如果只有一个脚本,则该参数是可选的,而-E
是一个开关。-e
仅当只有一个脚本时,删除“-E”才有效,因为无论如何它都是多余的。