如何在连续的重复行之间插入一行?

如何在连续的重复行之间插入一行?

我想添加一个虚拟 IP 地址,但只有在找到两个连续的重复行之后才能添加。

我正在 Linux 系统上工作,这是我的输入文件:

  IP_Remote_Address
     Address : 192.168.1.1
  IP_Remote_Address
     Address : 192.168.1.2
  IP_Remote_Address
     Address : 192.168.1.3
  IP_Remote_Address
  IP_Remote_Address
     Address : 192.168.1.4
  IP_Remote_Address
     Address : 192.168.1.5
  IP_Remote_Address
     Address : 192.168.1.6
  IP_Remote_Address
     Address : 192.168.1.7
  IP_Remote_Address
  IP_Remote_Address
     Address : 192.168.1.8

我想要的输出:

  IP_Remote_Address
     Address : 192.168.1.1
  IP_Remote_Address
     Address : 192.168.1.2
  IP_Remote_Address
     Address : 192.168.1.3
  IP_Remote_Address
     Address : NOT_FOUND
  IP_Remote_Address
     Address : 192.168.1.4
  IP_Remote_Address
     Address : 192.168.1.5
  IP_Remote_Address
     Address : 192.168.1.6
  IP_Remote_Address
     Address : 192.168.1.7
  IP_Remote_Address
     Address : NOT_FOUND
  IP_Remote Address
  Address : 192.168.1.8

我有这条线,但它仅替换找到的第一个重复项:

awk '{print $0; if((getline nl) > 0){ print ($0!="IP_Remote_Address" && $0 == nl)? nl=$0"INSERT_NOT_FOUND_ABOVE" : nl }}' file.txt

我稍后可以使用 sed 将字符串替换INSERT_NOT_FOUND_ABOVE"为:

sed '/INSERT_NOT_FOUND_ABOVE/i Address : NOT_FOUND' file.txt > new_file.txt

我唯一的问题是它无法检测所有连续的重复项;它只找到第一个。

答案1

awk:

awk 'p==$0{print "     Address : NOT_FOUND"}{p=$0}1'

一个相当幼稚的解决方案。

  • p==$0IF p == 当前行
    • 然后打印not found
  • p=$0SET p = 当前行
  • 1: 打印

处理连续的重复行。


正如所指出的@旧金山在有问题的评论中,“最后一个IP可能也不见了,对吧?”- UPS。应该想到这一点。

所以:

awk -v e='Address : NOT_FOUND' 'p==$0{print e}{p=$0}END{if($1 ~ "IP")print e}1'
  • Set e= 要注入的文本
  • p==$0IF p == 当前行
    • 然后打印变量e
  • p=$0SET p = 当前行
  • END打印e当前行是否包含IP
  • 1: 打印

这里的错误字符串由于我们使用了两次,因此已将其添加为变量。 (并在这篇文章中为了可读性而进行了修剪)。

答案2

她是在 GNU sed 中使用滑动窗口实现此目的的一种方法:

解析.sed

# Handle last-line-error
$ { /IP/ s/$/\n   Address : NOT_FOUND/; }

# Always keep 2 lines in pattern-space
N

# If the lines are identical
/^([^\n]*)\n\1$/ { 

  # Add error text
  s/\n/\n   Address : NOT_FOUND\n/

  # Ensure we still only have 2 lines in pattern-space
  P
  s/[^\n]*\n//
}

# Print line 1 and delete it from pattern-space
P
D

这是修改后的测试文本,带有三重错误和最后一行错误:

IP_Remote_Address
   Address : 192.168.1.1
IP_Remote_Address
   Address : 192.168.1.2
IP_Remote_Address
   Address : 192.168.1.3
IP_Remote_Address
IP_Remote_Address
IP_Remote_Address
IP_Remote_Address
   Address : 192.168.1.4
IP_Remote_Address
   Address : 192.168.1.5
IP_Remote_Address
   Address : 192.168.1.6
IP_Remote_Address
   Address : 192.168.1.7
IP_Remote_Address
IP_Remote_Address
   Address : 192.168.1.8
IP_Remote_Address

像这样运行它:

sed -Ef parse.sed infile

或者作为一句单行:

<infile sed -E '${/IP/ s/$/\n   Address : NOT_FOUND/};N;/^([^\n]*)\n\1$/{s/\n/\n   Address : NOT_FOUND\n/;P;s/[^\n]*\n//};P;D'

两种情况下的输出:

IP_Remote_Address
   Address : 192.168.1.1
IP_Remote_Address
   Address : 192.168.1.2
IP_Remote_Address
   Address : 192.168.1.3
IP_Remote_Address
   Address : NOT_FOUND
IP_Remote_Address
   Address : NOT_FOUND
IP_Remote_Address
   Address : NOT_FOUND
IP_Remote_Address
   Address : 192.168.1.4
IP_Remote_Address
   Address : 192.168.1.5
IP_Remote_Address
   Address : 192.168.1.6
IP_Remote_Address
   Address : 192.168.1.7
IP_Remote_Address
   Address : NOT_FOUND
IP_Remote_Address
   Address : 192.168.1.8
IP_Remote_Address
   Address : NOT_FOUND

答案3

在其扩展正则表达式模式下使用流编辑器实用程序 sed 的 GNU 版本:

sed -Ee '
  x;1d;G
  ${/\n\s*IP_/ba;}
  /^(.*)\n\1$/{
    g;:a;p;c\
   Address : NOT_FOUND
    b
  }
  $!s/\n.*//
' file
  • 当前行进入保存空间,前一行进入模式空间。
  • 当保持和模式空间(即上一行和当前行)之间存在匹配时,我们打印该行+未找到的行。
  • 最后一行是 /IP_/ 然后我们还添加未找到的行。

相关内容