如何用awk或sed在文本最后一个}前插入指定内容?
如何在文件最后一个
}前插入指定内容(sed/awk实现) 你之前用的sed -i "s/}$/content&/g"会匹配每一行末尾的},所以才会在所有行尾的}前加内容。要实现「整个文件最后一个}前插入内容」,得换个思路——要么先把文件反转处理第一个}再转回来,要么把整个文件读入内存后直接定位最后一个}。下面给你两种实用的方案:
方案一:用sed实现(GNU sed)
如果你的系统是GNU sed(比如Linux默认的sed),可以直接用下面的命令修改原文件:
sed -i -e '1!H;1h;$!d;x' -e 's/\(.*\)}/\1content}/' a.txt
命令解释:
1!H;1h;$!d;x:这部分是把整个文件的内容全部读入到模式空间(相当于把所有行拼接成一个整体)1h:第一行覆盖写入保持空间1!H:除第一行外,每行追加到保持空间$!d:除最后一行外,删除当前模式空间的内容(不输出)x:交换保持空间和模式空间,此时模式空间就是整个文件的内容
s/\(.*\)}/\1content}/:用贪婪匹配捕获最后一个}之前的所有内容,替换成「捕获内容 + 指定content +}」,这样就只修改了整个文件的最后一个}
如果是BSD sed(比如macOS的sed),语法略有不同,需要合并命令并指定备份文件:
sed -i.bak -e '1!H;1h;$!d;x;s/\(.*\)}/\1content}/' a.txt
执行完可以删掉生成的.bak备份文件。
另一种更直观的思路是借助tac反转文件,处理后再反转回来:
tac a.txt | sed '0,/}/{s/}/content&/}' | tac > a.txt.tmp && mv a.txt.tmp a.txt
命令解释:
tac:把文件的行顺序反转(原文件最后一行变成第一行)sed '0,/}/{s/}/content&/}':只匹配反转后文件的第一个}(也就是原文件的最后一个}),在它前面插入content- 再用
tac反转回原顺序,最后替换原文件
方案二:用awk实现
awk可以轻松把整个文件读入内存,然后定位最后一个}进行修改,兼容性更好:
awk '{buf = buf $0 ORS} END {sub(/(.*)}/, "\\1content}", buf); printf "%s", buf}' a.txt > a.txt.tmp && mv a.txt.tmp a.txt
命令解释:
{buf = buf $0 ORS}:把每一行内容追加到变量buf里,ORS是输出行分隔符(默认是换行),保证格式和原文件一致END {sub(/(.*)}/, "\\1content}", buf); printf "%s", buf}:处理完所有行后,用sub做一次贪婪匹配替换,把最后一个}前面插入content,最后输出修改后的内容
如果你的awk是gawk(GNU awk),还可以用更简洁的gensub:
gawk '{buf = buf $0 ORS} END {print gensub(/(.*)}/, "\\1content}", 1, buf)}' a.txt > a.txt.tmp && mv a.txt.tmp a.txt
内容的提问来源于stack exchange,提问作者Xiaoer
相关产品推荐
相关产品推荐

