在BASH文件中找到匹配后,如何删除上面的两行?

时间:2015-06-11 12:32:41

标签: bash awk sed grep

我有一个包含以下数据的文件:

  1. 123
  2. 456
  3. 789
  4. 当我找到匹配789时,我想删除上面两行(123和456)。是否可以使用sed或awk进行操作?请帮忙

5 个答案:

答案 0 :(得分:3)

使用ed,标准编辑器:

ed -s file <<< $'3,$g/789/-2,.d\nw'

ed会看到以下命令:

3,$g/789/-2,.d
w

说明:

3,$g/789/

会将第3行 * 中的所有行标记到与/789/匹配的文件末尾;然后,对于每个标记的行,它将执行命令:

-2,.d

表示:删除范围-2,.,即在当前一行(-2)上方开始两行的范围,并在此处结束(.)。

然后w表示写入文件。如果您想首先尝试而不写入文件,而是在终端上打印(出于测试目的),请将w命令替换为,pQ,如下所示:

ed -s file <<< $'3,$g/789/-2,.d\n,p\nQ'

请注意。 ed确实编辑了文件(它是一个编辑器),所以它会愉快地保留符号链接和权限,这与所有其他依赖适用于流的工具的方法不同(sedawk

请注意。如果您的模式出现在前两行中,它将被保留(但是,这可以通过添加一些额外的命令来处理);如果你的模式出现在2行的范围内,你可能会有一些惊喜,例如,

000
123
456
789
123
789

将产生一个空文件,

123
456
789
123
789

你会收到错误。

* 范围从第3行开始,只是为了防止错误,以防你的模式出现在前两行

答案 1 :(得分:1)

此脚本不会将整个文件加载到内存中,这与其他一些答案不同,因此它对大文件有效,并假设您至少有3行

#n
1{
    N
    h
    n
    :loop
    ${      
        /789/! {
               x
               p
               g                   
        }
        p
    }
    $!{
        H
        g
        P
        s/^[^\n]*\n//
        h
        n
        b loop
    }
}

如果将其保存为s.sed,则可以运行

sed -f s.sed file

如果最后一行与789匹配,它将删除最后一行之前的两行。

输入:

123
456
789

输出:

789

输入:

abc
123
456
789

输出:

abc
789

输入:

123
456
abc

输出:

123
456
abc

<强>解释

#n会抑制正常输出。在与1匹配的第一行,我们在N附加下一行,并将其复制到保留空间h。然后我们使用n转到下一行,然后启动:loop

如果当前行是由$获取的最后一行,那么我们检查它是否与789不匹配,在这种情况下,我们交换模式并使用x保留空格,使用p打印出新的模式空间,然后使用g将保留空间复制到模式空间。最后我们打印出最后一行。

如果当前行不是最后一行。我们使用H将当前行附加到保留空间,然后将保留空间复制到模式空间。我们使用P打印图案空间的第一行,然后使用s/^[^\n]*\n//删除第一行。我们将其复制回保留空间,转到下一行,然后使用b loop重复循环。

答案 2 :(得分:1)

这可能适合你(GNU sed):

sed ':a;N;s/\n/&/2;Ta;/\n789$/s/.*\n//;P;D' file

在图案空间中保持3行的移动窗口,如果第3行是所需图案,则删除前两行。

答案 3 :(得分:0)

将文件加载到内存中(因此不适用于大文件)

sed '1h;1!H;$!d
     x;/\n[0-9]\{1,\}\.[[:space:]]\{1,\}789$/ s/\(\(\n\)[[:alnum:][:blank:][:punct:]]*\)\{3\}$/\2789/
    ' YourFile

将文件加载到内存中,检查最后一行是否匹配,如果是,则删除上一行2,打印结果

答案 4 :(得分:0)

要求救援!

awk '{a[NR]=$0} END{for(i=1;i<=NR;i++) if(a[i+1] a[i+2]!~/789/) print a[i]}' test.1
  

输入(test.1)

1. 123
2. 456
3. 789
4. 012
5. 345
6. 678
7. 901
8. 789
9. 111
  

输出

3. 789
4. 012
5. 345
8. 789
9. 111