使用GNU sed替换首个匹配模式,排除前置指定模式的问题
我来帮你搞定这个sed的问题~你的原命令的问题在于,0,/cat.*bird +[0-9]+/b只会跳过从文件开头到第一个匹配cat.*bird +[0-9]+的行,但之后的行不管是否包含cat在bird前面,都会执行替换操作——比如第三行的bird 3456虽然前面有cat,但它不在0,/cat.*bird +[0-9]+/的范围内,所以会被错误替换。
要实现你的需求(仅替换第一个满足「所在行中bird之前没有cat」的bird [数字]),我们需要用sed的保持空间来跟踪「是否已经完成替换」的状态,同时检查每行内cat和bird的位置关系。
这里给出正确的GNU sed命令:
sed -E ' # 切换到保持空间,检查是否已经完成过替换 /^/x /replaced/{ x b # 已替换过,直接输出当前行 } x # 如果当前行中cat在bird数字前面,直接输出不处理 /cat.*bird +[0-9]+/b # 否则,检查是否是bird+数字的行,若是则替换并标记状态 /(bird +)[0-9]+/{ s//\10/ # 将保持空间设为"replaced",标记已完成替换 h s/.*/replaced/ x } ' 你的文件名.txt
我们来拆解一下这个命令的逻辑:
- 每一行开始时,先切换到保持空间检查是否有
replaced标记——如果有,说明已经替换过目标行,直接输出当前行即可。 - 检查当前行是否存在
cat出现在bird [数字]之前的情况(匹配cat.*bird +[0-9]+),如果是,直接输出不处理。 - 如果当前行是符合条件的
bird [数字](没有cat在前面,且是第一个这样的行),就把数字替换为0,然后在保持空间写入replaced标记,确保后续行不再执行替换。
用你的示例文本测试这个命令,就能得到预期的结果:
dog cat - fish bird 123
dog fish - bird 0
dog - cat fish, lion bird 3456
内容的提问来源于stack exchange,提问作者Ryszard Czech
相关产品推荐
相关产品推荐

