sed中[]\.*]*重复替换异常的原因及修复方法求助
sed正则替换的异常行为分析与修复方法
正常匹配示例
要替换a或b的连续重复序列,使用[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
如果去掉正则中的*,逐个替换目标字符则结果正常:
$ echo "a \.*] b " | sed -n 's/[]\.*]/X/pg' a XXXX b
原因分析
问题根源在于*的匹配规则:它表示匹配前面的元素0次或多次,这意味着空字符串也会被视为匹配项。在g全局替换模式下,sed会遍历整个字符串的每个位置——包括字符之间的空隙、字符串开头和结尾的空位置——这些空位置都会被[]\.*]*匹配(0次匹配),进而被替换成X,最终出现大量多余的替换结果。
之前[ab]*处理abab时看似正常,其实是因为整个连续的abab被一次性替换成X,而其他空位置的替换结果被覆盖,所以最终只显示一个X,本质上同样存在空字符串匹配的问题。
修复方法
使用+替代*,+表示匹配前面的元素1次或多次,不会匹配空字符串。需要注意:
- GNU sed默认不启用扩展正则,需添加
-E参数:
$ echo "a \.*] b " | sed -nE 's/[]\.*]+/X/gp' a X b
- 若不想用
-E,可以使用POSIX基本正则的转义写法\+:
$ echo "a \.*] b " | sed -n 's/[]\.*]\+/X/gp' a X b
环境信息
- 操作系统:Mac OS 13.0.1 (22A400)
- sed版本:GNU sed 4.9
内容的提问来源于stack exchange,提问作者mon
相关产品推荐
相关产品推荐

