regex sed -解释奇怪的行为,以取代重复的]\,*

new9mtju  于 2023-10-22  发布在  其他
关注(0)|答案(2)|浏览(197)

请帮助理解下面的意外sed行为以及如何修复。
要替换ab的重复,我可以使用[ab]*

$ echo "abab" | sed -n 's/[ab]*/X/gp'
X

然而,[]\.*]*并不像预期的那样产生a X b,如下所示,导致额外的替换。

$ echo "a \.*] b " | sed -n 's/[]\.*]*/X/pg'
XaX X XbX X

如果在regexp模式中逐个替换而不重复表达式*,则可以工作。

$ echo "a \.*] b " | sed -n 's/[]\.*]/X/pg'
a XXXX b

因此,我怀疑重复表达式*导致了这个问题,但不确定是什么问题。
工作环境:

Mac OS 13.0.1 (22A400)

$ sed --version
sed (GNU sed) 4.9
g6ll5ycj

g6ll5ycj1#

我发现有趣的是,字符类允许在第一个位置使用闭合方括号,而不使用转义符。这是我不知道的好速记。

echo '1[]2[]3[]4' | sed 's/[]]/x/g'
1[x2[x3[x4

我认为]需要转义为\],但第一个位置似乎也使反斜杠成为文字反斜杠:

echo '1[]2[]3[]4' | sed 's/[\]]*/x/g'
1[]2[]3[]4

.这令人惊讶地没有替换任何东西,因为它正在寻找文字反斜杠来锚匹配。
所以这有助于理解这里发生了什么:

$ echo '1[\]2[\]3[\]4' | sed 's/[\]/x/g'
1[x]2[x]3[x]4
$ echo '1[\]2[\]3[\]4' | sed 's/[\]]/x/g'
1[x2[x3[x4

第二个是困惑。为什么只有一个x?哦,因为它匹配\]作为单一匹配。
所以,我必须得出结论,],结束方括号必须在字符类中除了第一个位置之外的任何地方进行转义。对于\,反斜杠也是一样的(但在最后一个位置也是允许的)。原来IEEE标准也支持这个。]部分。\的含义必须在其他地方讨论。
另一件发生的事情是*意味着“零次或多次出现”,所以你也会看到替换匹配所有字符边界:

echo '1[]2[]3[]4' | sed 's/[]]*/x/g'
x1x[x2x[x3x[x4x

对我来说这没什么好惊讶的正如评论所说,在BRE中,您可以使用\+而不是*来表示“一个或多个”。
最后,“或更多”可能会令人困惑:

$ echo abab | sed 's/[ab]*/X/g;'
X
$ echo abab | sed 's/[ab]/X/g;'
XXXX
$ echo abcab | sed 's/[ab]/X/g;'
XXcXX
$ echo abcab | sed 's/[ab]*/X/g;'
XcX

是的[ab]*将匹配a和B的不间断字符串作为 * 单个 * 匹配。

sqxo8psd

sqxo8psd2#

你从echo "abab" | sed -n 's/[ab]*/X/gp'开始。
这看起来很好,因为您的输入只有匹配的字符。你有同样的问题与另一个输入字符串。

echo "string with abab inside" | sed -n 's/[ab]*/X/gp'
XsXtXrXiXnXgX XwXiXtXhX X XiXnXsXiXdXeX

这是因为*也匹配长度为0的字符串。
您可以通过将*替换为\+来修复它。

echo "string with abab inside" | sed -n 's/[ab]\+/X/gp'
string with X inside

# Or avoid the backslash with the '-r' option
echo "string with abab inside" | sed -rn 's/[ab]+/X/gp'
string with X inside

你的情况与其他字符集的工作方式相同。

echo "a \.*] b " | sed -n 's/[]\.*]\+/X/pg'
a X b

有了BRE,就像

echo "a \.*] b " | sed -rn 's/[]\.*]{1,}/X/pg'
a X b

相关问题