【发布时间】:2021-09-20 19:38:22
【问题描述】:
有什么方法可以用 sed 替换文件中第 n 次出现的字符串?
如何更改它以替换第 n 次出现?
我的文件内容如下:
first line
second line
third line
jack
fifth line
jack
seventh line
考虑一个变量var = jill。
我想用变量$var 的值替换第二次出现的jack。
【问题讨论】:
标签: sed
有什么方法可以用 sed 替换文件中第 n 次出现的字符串?
如何更改它以替换第 n 次出现?
我的文件内容如下:
first line
second line
third line
jack
fifth line
jack
seventh line
考虑一个变量var = jill。
我想用变量$var 的值替换第二次出现的jack。
【问题讨论】:
标签: sed
这可能对你有用(GNU sed):
sed ':a;$!{N;ba};s/jack/'"$var"'/2' file
这会将文件吞入内存,然后将第二次出现的jack 替换为$var。
编辑:
:a 是 b 命令的占位符,它告诉 sed 中断/跳转到位置,即 ba 跳转到 :a。$! 是一个地址。 $ 表示文件结束,! 表示不是。放在一起这意味着任何不是文件结尾的地址。{...} 将大括号之间的命令分组。N 追加一个换行符,然后将下一行追加到模式空间,除非当它通过 sed 到刚刚传递最后一个命令时没有更多行(如果 -n 未设置,它将打印模式中的任何内容空格,如果设置了-n,它将结束处理)。s/jack/'$var"'/2 这是一个 sed 替换命令,将第二次出现的 jack 替换为 $var 的内容。注: '...' 有效地将 sed 命令分解到底层 shell,然后再次返回,允许插入 shell 变量。总之,整个文件被吞入内存,第二次出现的jack 被$var 的内容替换。
在大多数情况下,这可以替换为:
sed -z 's/jack/'"$var"'/2' file
【讨论】:
</Attribute> 不是。如果斜线在模式和替换中很常见,最好使用替代分隔符,例如#
:a;$!{N;ba}; 将完整的文件读入模式空间。
如果您喜欢使用awk,这里是awk 版本
awk -v c="$var" '/jack/ && ++a==2 {sub(/jack/,c)}1' file
first line
second line
third line
jack
fifth line
jill
seventh line
【讨论】:
echo "jack" | awk '{s=length($1)/2;print substr($1,0,s)"jill"substr($1,s+1)}'