在bash中匹配前后删除行(使用sed或awk)?

jul*_*ert 7 shell awk sed

我试图从一个充满交易的文件中删除模式匹配两侧的两行.IE浏览器.找到匹配然后删除它之前的两行,然后删除它后面的两行,然后删除匹配.将此写回原始文件.

所以输入数据是

D28/10/2011
T-3.48
PINITIAL BALANCE
M
^
Run Code Online (Sandbox Code Playgroud)

我的模式是

sed -i '/PINITIAL BALANCE/,+2d' test.txt
Run Code Online (Sandbox Code Playgroud)

但是,这只是在模式匹配后删除两行,然后删除模式匹配.我无法使用sed以任何逻辑方式从原始文件中删除所有5行数据.

Ken*_*ent 6

awk单行可以完成这项工作:

awk '/PINITIAL BALANCE/{for(x=NR-2;x<=NR+2;x++)d[x];}{a[NR]=$0}END{for(i=1;i<=NR;i++)if(!(i in d))print a[i]}' file
Run Code Online (Sandbox Code Playgroud)

测试:

kent$  cat file
######
foo
D28/10/2011
T-3.48
PINITIAL BALANCE
M
x
bar
######
this line will be kept
here
comes
PINITIAL BALANCE
again
blah
this line will be kept too
########

kent$  awk '/PINITIAL BALANCE/{for(x=NR-2;x<=NR+2;x++)d[x];}{a[NR]=$0}END{for(i=1;i<=NR;i++)if(!(i in d))print a[i]}' file
######
foo
bar
######
this line will be kept
this line will be kept too
########
Run Code Online (Sandbox Code Playgroud)

添加一些解释

  awk '/PINITIAL BALANCE/{for(x=NR-2;x<=NR+2;x++)d[x];}   #if match found, add the line and +- 2 lines' line number in an array "d"
      {a[NR]=$0} # save all lines in an array with line number as index
      END{for(i=1;i<=NR;i++)if(!(i in d))print a[i]}' #finally print only those index not in array "d"
     file  # your input file
Run Code Online (Sandbox Code Playgroud)


rus*_*ush 5

sed 会做的:

sed '/\n/!N;/\n.*\n/!N;/\n.*\n.*PINITIAL BALANCE/{$d;N;N;d};P;D'
Run Code Online (Sandbox Code Playgroud)

它是这样工作的:

  • 如果 sed 在模式空间中只有一个字符串,它会连接另一个字符串
  • 如果只有两个它加入第三个
  • 如果它确实使用 BALANCE 模式 LINE + LINE + LINE 它连接以下两个字符串,删除它们并从头开始
  • 如果没有,它打印模式中的第一个字符串并删除它并从头开始而不刷模式空间

为了防止在第一个字符串上出现模式,您应该修改脚本:

sed '1{/PINITIAL BALANCE/{N;N;d}};/\n/!N;/\n.*\n/!N;/\n.*\n.*PINITIAL BALANCE/{$d;N;N;d};P;D'
Run Code Online (Sandbox Code Playgroud)

但是,如果您有另一个PINITIAL BALANCE要删除的字符串,它会失败。但是,其他解决方案也失败了 =)


小智 5

更简单且易于理解的解决方案可能是:

awk '/PINITIAL BALANCE/ {print NR-2 "," NR+2 "d"}' input_filename \
    | sed -f - input_filename > output_filename
Run Code Online (Sandbox Code Playgroud)

awk 用于制作一个 sed 脚本,删除有问题的行,并将结果写入输出文件名。

这使用了两个可能比其他答案效率低的过程。