CentOS7环境下sed替换文件第二次及之后匹配项不生效问题求助
解决方案
错误命令原因说明
你之前尝试的命令中,替换标记的数字仅对单行内的匹配次序生效:
s/foo/bar/2:仅替换每一行内的第2个foos/foo/bar/2g:替换每一行内第2个及之后的所有foo
这两个逻辑都是行内维度的,无法实现跨所有行的全局第2次及之后替换的需求。
正确实现方法
CentOS 7 内置GNU sed,可通过保留空间计数实现全局匹配计数替换,命令如下:
1. 预览替换效果(不修改原文件)
sed -e '/foo/{x;s/^/x/;/x\{2,\}/{x;s/foo/bar/g;b};x}' 你的文件名
2. 直接修改原文件
添加-i参数即可直接写入原文件:
sed -i -e '/foo/{x;s/^/x/;/x\{2,\}/{x;s/foo/bar/g;b};x}' 你的文件名
命令逻辑说明
- 每次匹配到
foo时,将当前行和保留空间内容交换 - 给保留空间追加1个字符
x作为计数标记 - 判断保留空间内
x的数量≥2时,换回当前行,将该行所有foo替换为bar后直接输出当前行 - 若
x数量不足2,换回当前行不做替换
简化方案(仅适用于所有foo分布在不同行的场景)
如果你的场景中每行最多只有1个foo(和你提供的测试文件一致),可以用更简单的范围匹配写法:
# 预览效果 sed '0,/foo/!s/foo/bar/g' 你的文件名 # 直接修改文件 sed -i '0,/foo/!s/foo/bar/g' 你的文件名
这个写法的逻辑是:匹配从文件开头到第一个foo出现的范围,范围外的所有行里的foo全部替换为bar。
测试效果验证
针对你提供的测试文件,执行上述命令后输出结果为:
this foo is a test file this bar
完全符合从第二次出现foo开始替换的需求。
内容的提问来源于stack exchange,提问作者Utz
相关产品推荐
相关产品推荐

