我正在尝试从一个充满交易的文件中删除模式匹配两侧的两行。 IE浏览器。找到匹配然后删除它之前的两行,然后删除它后面的两行,然后删除匹配。将此写回原始文件。
所以输入数据是
D28/10/2011
T-3.48
PINITIAL BALANCE
M
^
我的模式是
sed -i '/PINITIAL BALANCE/,+2d' test.txt
然而,这只是在模式匹配后删除两行,然后删除模式匹配。我无法用任何合理的方法使用sed从原始文件中删除所有5行数据。
答案 0 :(得分:6)
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
试验:
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
########
添加一些解释
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
答案 1 :(得分:4)
sed将会这样做:
sed '/\n/!N;/\n.*\n/!N;/\n.*\n.*PINITIAL BALANCE/{$d;N;N;d};P;D'
它的工作方式如下:
要防止出现第一个字符串上的模式,你应该修改脚本:
sed '1{/PINITIAL BALANCE/{N;N;d}};/\n/!N;/\n.*\n/!N;/\n.*\n.*PINITIAL BALANCE/{$d;N;N;d};P;D'
然而,如果您在字符串中有另一个PINITIAL BALANCE
将被删除,则会失败。然而,其他解决方案也失败了=)
答案 2 :(得分:1)
对于这样的任务,我可能会找到更高级的工具,如Perl:
perl -ne 'push @x, $_;
if (@x > 4) {
if ($x[2] =~ /PINITIAL BALANCE/) { undef @x }
else { print shift @x }
}
} END { print @x'
答案 3 :(得分:1)
这可能适合你(GNU sed):
sed ':a;$q;N;s/\n/&/2;Ta;/\nPINITIAL BALANCE$/!{P;D};$q;N;$q;N;d' file
答案 4 :(得分:0)
将此代码保存到文件grep.sed
H
s:.*::
x
s:^\n::
:r
/PINITIAL BALANCE/ {
N
N
d
}
/.*\n.*\n/ {
P
D
}
x
d
并运行如下命令:
`sed -i -f grep.sed FILE`
您可以使用它:
sed -i 'H;s:.*::;x;s:^\n::;:r;/PINITIAL BALANCE/{N;N;d;};/.*\n.*\n/{P;D;};x;d' FILE
答案 5 :(得分:0)
更简单易懂的解决方案可能是:
awk '/PINITIAL BALANCE/ {print NR-2 "," NR+2 "d"}' input_filename \
| sed -f - input_filename > output_filename
awk 用于制作一个 sed 脚本,删除有问题的行并将结果写入 output_filename。
这使用了两个可能比其他答案效率低的过程。