为何带‘g’修饰符的sed命令无法替换所有匹配内容?
问题解答:带
g修饰符的sed命令无法替换所有匹配内容 问题重现
示例命令:
$ sed -e 's:foo\([^\s]*\):\1 :g' <(echo "hey foobar foobar ")
预期输出:
hey bar bar
实际输出:
hey bar foobar
核心原因
你忽略的关键细节是:\s并非POSIX标准的正则元字符,部分sed版本(如macOS默认sed)不支持该语法。
当sed无法识别\s时,会将其视为普通字符s,此时正则中的[^\s]*会被解析为「匹配除字符s之外的所有字符」——这其中包括空格。第一个匹配会从第一个foo开始,直接匹配到行尾(整个输入字符串中没有s),把foobar foobar 替换成bar foobar ,后续没有剩余的foo可供匹配,g全局修饰符自然无法生效。
解决方案
改用POSIX标准的空白字符类[[:space:]]替代\s,修改后的命令如下:
$ sed -e 's:foo\([^[:space:]]*\):\1 :g' <(echo "hey foobar foobar ")
如果仅需匹配空格和制表符,也可以使用[[:blank:]],在这个场景下效果一致。
若你使用的是GNU sed(Linux系统默认版本),原本是支持\s的,若仍出现问题,可检查是否开启了POSIX兼容模式(如添加了--posix参数),该模式下\s会失效。
内容的提问来源于stack exchange,提问作者Daniel Tiger
相关产品推荐
相关产品推荐

