如何使用sed替换identifier {行后item路径且不丢失后续行内容
问题场景
- 现有输入文件内容如下:
this is text identifier { item /directory/file_1234 some more text item /directory/file_1234 other line text identifier { item /directory/98_76file other line
- 需求:将所有出现在
identifier {行之后、匹配item /directory/*规则的字符串的路径部分替换为/directory/file_ABC,其余所有行内容完整保留,不得误删。 - 原命令异常原因:原命令通过
:a;N;$!ba将整个文件读入内存拼接为单行,后续正则中使用的.*为贪婪匹配,会直接吞掉首次匹配位置到文件末尾的所有内容,导致后续行全部被擦除。
正确sed实现方案
针对给出的样例场景(每个identifier {行后紧跟目标item行),使用如下命令即可完成精准替换:
sed '/identifier {/{n;s|\(.*item \)/directory/.*|\1/directory/file_ABC|}' input
命令逻辑说明
- 逐行扫描文件,匹配到包含
identifier {的行时,先原样输出当前行,再读取紧邻的下一行 - 对读取到的下一行执行替换:保留行首缩进、
item前缀,将后续匹配/directory/任意内容的路径部分替换为目标路径/directory/file_ABC - 所有不满足匹配规则的行全部原样输出,不会做任何修改
执行后预期输出
this is text identifier { item /directory/file_ABC some more text item /directory/file_1234 other line text identifier { item /directory/file_ABC other line
如果存在identifier {块下包含多个连续item行需要替换的场景,可以使用带状态循环的通用版本:
sed ' /identifier {/ { :mark n /item \/directory\// s|/directory/.*|/directory/file_ABC| /^[[:space:]]*$/ b mark /^[[:space:]]\+item / b mark } ' input
该版本会在匹配到identifier {后持续检查后续行,只要是缩进开头的空行、item行就持续处理,直到碰到非块内的普通行就退出替换状态,不会影响块外内容。
内容的提问来源于stack exchange,提问作者xavi
相关产品推荐
相关产品推荐

