sed / awk 匹配文件中第二次出现的正则表达式,并替换整行

sed / awk match second occurrence of regex in a file, and replace whole line

尝试让 sed 或 awk 执行以下操作:

  1. 浏览文件
  2. 捕获字符串 + 正则表达式 (remote_addrs.*)
  3. 将整行替换为不同的内容,因此“包含“remote_addrs”及其后任何内容的行”将其替换。

示例文件:

dog
cat
remote_addrs = 1.1.1.1
moose
remote_addrs = 2.2.2.2
woodchuck

想改成这样: 示例文件:

dog
cat
remote_addrs = 1.1.1.1
moose
remote_addrs = 3.3.3.3
woodchuck

尝试使用以下方法:

sed -z 's/remote_addrs.*/remote_addrs\ =\ 3.3.3.3/2' file
sed ':a;N;$!ba;s/remote_addrs.*/remote_addrs\ =\ 3.3.3.3/2' file

但 sed 拒绝在发生该事件后替换所有内容。这似乎只适用于单个字符串。

这个必须完成不给出具体的行号,“remote_addrs”的行位置必须是可变的。

您使用的是 GNU sed,所以我也发布一个 GNU sed 解决方案:

sed -z 's/remote_addrs.*/remote_addrs = 3.3.3.3/2m' file

注:

  • </code>(在您现在编辑的问题的初始版本中使用)是对第 3 组的反向引用,并且您的正则表达式中没有单个组。因此,应删除转义符</li> <li>你不需要转义 spaces</li> <li><code>\z 使换行符成为模式 space 的一部分,因此 . 匹配它们。您需要打开“多行”模式,并添加 m 标志,以便 . 模式无法匹配换行字符。

参见online demo

#!/bin/bash
s='dog
cat
remote_addrs = 1.1.1.1
moose
remote_addrs = 2.2.2.2
woodchuck'
 
sed -z 's/remote_addrs.*/remote_addrs = 3.3.3.3/2m' <<< "$s"

输出:

dog
cat
remote_addrs = 1.1.1.1
moose
remote_addrs = 3.3.3.3
woodchuck

虽然 Wiktor 的 nice 解决方案已被接受,但 awk 解决方案如何 (JFYI):

awk '/remote_addrs.*/ && c++==1 {sub(/remote_addrs.*/, "remote_addrs = 3.3.3.3")} 1' file
  • 正则表达式的第一个匹配只是递增变量 c 而没有调用 {...}.
  • 中的语句
  • 第二个匹配执行sub()语句。
  • 最后的1告诉awk打印当前记录。

使用 awk 你可以试试这个

$ cat file
dog
cat
remote_addrs = 1.1.1.1
moose
remote_addrs = 2.2.2.2
woodchuck

$ awk 'set==1 && /remote_addrs/{ [=10=]="remote_addrs = 3.3.3.3" }
    /remote_addrs/{ set=1 } 1' file
dog
cat
remote_addrs = 1.1.1.1
moose
remote_addrs = 3.3.3.3
woodchuck