如何使用sed将文件匹配start到end的多行范围替换为另一文件内容
问题解决方案
报错原因
event not found: d是Bash默认开启的历史扩展机制导致的:!字符会被识别为调用历史命令的触发器,即使!包裹在单引号内、外层再套双引号的场景下也会触发解析,最终因为找不到对应d的历史命令抛出报错。
另外你当前使用的命令逻辑本身存在问题:sed的r指令仅会将读取的文件内容追加到匹配行之后,不会自动删除start到end之间的原有内容,无法实现区间替换的效果。
正确实现方案
你的需求为匹配file_1中start到end的唯一多行区间,替换为file_2的全部内容,可根据运行环境选择对应命令:
Linux(GNU Sed 环境)
# 临时关闭历史扩展避免!相关报错 set +o histexpand sed -i '/start/,/end/{/end/{r file_2 :a;n;ba};d}' file_1
macOS(BSD Sed 环境)
# 临时关闭历史扩展避免!相关报错 set +o histexpand sed -i '' '/start/,/end/{/end/{r file_2 :a;n;ba};d}' file_1
逻辑说明
- 用
/start/,/end/匹配两个标记之间的所有行 - 对匹配区间内的行,除最后一行
end外全部直接删除 - 匹配到
end行时,先通过r指令读取file_2的全部内容插入到当前位置,再循环删除区间剩余的所有内容,最终实现原区间整体替换为file_2内容的效果
额外说明
如果你需要先处理file_2的内容再替换(比如你原命令中的只保留前2行),只需要把命令中的file_2替换为<(sed '1,2!d' file_2)即可,已经关闭历史扩展的场景下不会再触发!相关报错。
内容的提问来源于stack exchange,提问作者newbieeng
相关产品推荐
相关产品推荐

