如何用awk/sed替换两个tag间文本为指定变量内容?
问题解决:替换两个tag行之间的内容
问题背景
我在Stack Exchange系列平台搜过不少类似问题,但没找到完全贴合需求的方案。现有一个文件内容如下:
bla bla bla tag text 1 text 2 tag bla bla
另外有个变量X,内容是:
alpha beta gamma
需要用awk或sed实现:删掉两个tag行之间的文本,替换成X的内容,最终得到:
bla bla bla tag alpha beta gamma tag bla bla
之前试了这条awk命令,但它会把tag删掉,还重复插入两次X:
awk -v var="$X" 'BEGIN{RS=""; FS="\n"} /tag/ {print var; next} {print $0"\n"}'
可行方案
方案1:用awk实现(推荐)
用状态标记控制是否跳过原区间内容,逻辑清晰直接:
awk -v var="$X" ' /^tag$/ { print $0 if (in_tag) { in_tag = 0 } else { in_tag = 1 print var } next } !in_tag {print $0} ' 你的文件名
逻辑说明:
- 碰到
tag行时,先把tag本身打印出来; - 如果之前已经标记过进入
tag区间(in_tag=1),就把状态切回0,退出区间; - 如果是第一次遇到
tag,标记进入区间,然后直接打印变量X的内容; - 只有不在
tag区间里的时候,才打印原文件的行,自动跳过原区间里的text 1、text 2这些内容。
方案2:用sed实现
sed需要先处理变量里的换行和特殊字符,再执行区间替换:
# 先转义X里的特殊字符,把换行换成sed能识别的\n escaped_X=$(printf '%s\n' "$X" | sed 's/[\&/]/\\&/g; $!s/$/\\n/') # 执行替换 sed "/^tag$/,/^tag$/{//!d; /^tag$/n; s/^/$escaped_X/}" 你的文件名
逻辑说明:
- 第一步转义是因为sed里
&、/这些字符有特殊含义,换行也要换成\n才能被sed解析成多行; "/^tag$/,/^tag$/"匹配两个tag之间的所有行://!d:删掉区间里不是tag的行;/^tag$/n:遇到第一个tag后,读取下一行(原来区间里的第一行);s/^/$escaped_X/:把这一行替换成转义后的X内容,相当于把X插入到两个tag之间。
内容的提问来源于stack exchange,提问作者lord_nimon
相关产品推荐
相关产品推荐

