sed [^] 中的锚字符

sed [^] 中的锚字符

为什么当我们使用否定表达式时,sed[^ ]会将锚字符视为\b真实\B字符?例如,人们可能期望以下表达式产生相同的结果,但事实并非如此:

$ echo 'apple pear melon banana cherry papaya' | sed 's/[^\b]a[^\b]/u/g'
apple pu melon baua cherry uaya
$ echo 'apple pear melon banana cherry papaya' | sed 's/\Ba\B/u/g'
apple peur melon bununa cherry pupuya

如果没有\B,我们怎么能否定呢\b

答案1

两者都不是\b\B是字符。两者都是匹配的零宽度模式之间人物。

\b模式在单词边界处匹配,即在作为“单词字符”的字符和不是“单词字符”的字符之间匹配。

\B模式在非单词边界处匹配,即在两个字符之间匹配,这两个字符要么是“单词字符”,要么不是。

模式[^\b]匹配一个字符。这就是为什么pear转化为pu,你替换ear(thea和周围的字符)。

对于 GNU sed,匹配不是 an或 a 的[^\b]字符。\b

没有办法使用字符类来代替\B我所知道的字符类的使用。

GNU 支持\b和模式。 GNU和 BSD都有and用于在单词的开头和结尾显式匹配,并且 BSD还支持 POSIX 模式and (但 GNU不支持)。 POSIX 模式无法被否定(不起作用)。\Bsedsedsed\<\>sed[[:<:]][[:>:]]sed[^[:>:]]

为了得到一个相似的效果而不使用\B,你可以使用类似的东西

$ echo 'apple pear melon banana cherry papaya' | sed 's/\([[:alnum:]]\)a\([[:alnum:]]\)/\1u\2/g'
apple peur melon bunana cherry pupaya

也就是说,匹配 两侧的字母数字字符a,然后在替换中包含这两个侧翼字符。请注意,由于替换仅发生在非重叠匹配项中,因此这不会正确替换包含多个连续'(或每隔一个位置都有 ')a的字符串中的 ' 。看看如何不会因为这个而出现。aabananabununa

为了解决这个问题,您可以在sed程序中引入一个循环:

sed -e :top -e 's/\([[:alnum:]]\)a\([[:alnum:]]\)/\1u\2/g' -e ttop

这会根据需要对输入行执行多次替换,直到处理完所有重叠的模式匹配。

相关内容