Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/bash/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在BASH中找到匹配文件后,如何删除上面的两行?_Bash_Awk_Sed_Grep - Fatal编程技术网

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

在BASH中找到匹配文件后,如何删除上面的两行?,bash,awk,sed,grep,Bash,Awk,Sed,Grep,我有一个包含以下数据的文件: 123 456 789 当我找到匹配项789时,我想删除上面两行(123和456)。是否可以使用sed或awk进行此操作?请帮助将文件加载到内存中(因此对于大文件来说不是最好的选择) 将文件加载到内存中,检查最后一行是否匹配,如果是,则删除前两行,打印结果与其他一些答案不同,此脚本不会将整个文件加载到内存中,因此它对大文件非常有效,并且假设您至少有3行 #n 1{ N h n :loop ${ /7

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

  • 123
  • 456
  • 789

  • 当我找到匹配项789时,我想删除上面两行(123和456)。是否可以使用sed或awk进行此操作?请帮助

    将文件加载到内存中(因此对于大文件来说不是最好的选择)


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

    与其他一些答案不同,此脚本不会将整个文件加载到内存中,因此它对大文件非常有效,并且假设您至少有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
    
    abc
    123
    456
    789
    
    123
    456
    abc
    
    输出:

    789
    
    abc
    789
    
    123
    456
    abc
    
    输入:

    123
    456
    789
    
    abc
    123
    456
    789
    
    123
    456
    abc
    
    输出:

    789
    
    abc
    789
    
    123
    456
    abc
    
    输入:

    123
    456
    789
    
    abc
    123
    456
    789
    
    123
    456
    abc
    
    输出:

    789
    
    abc
    789
    
    123
    456
    abc
    
    解释

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

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

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

    awk重复循环以拯救

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


    使用
    ed
    ,标准编辑器:

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

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

    -2,.d
    
    这意味着:删除范围
    -2,.
    ,即从当前(
    -2
    )上方的两行开始并在此处结束(
    )的范围

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

    ed -s file <<< $'3,$g/789/-2,.d\n,p\nQ'
    
    将生成一个空文件,并且

    123
    456
    789
    123
    789
    
    你会得到一个错误


    *该范围从第3行开始,只是为了防止模式出现在前两行时出错,这可能适合您(GNU sed):


    在模式空间中保留一个3行的移动窗口,如果第三行是所需的模式,则删除前两行。

    文件是否包含1,2。等等。还有?几个匹配的情况如何(删除表start unitl last match或仅删除匹配的前两行?如果匹配在第一行或第二行怎么办?是的,我的文件包含序列号numbers@NeronLeVelu我只想在匹配后删除前两行,并且匹配必须在最后一行。对“是否可能”的回答总是“是”所以,不要问这个问题。编辑你的问题,以显示一些更具代表性的示例输入和预期输出。根据你目前发布的内容,一个解决方案会产生明显的预期效果。这会为我打印所有行。哪个版本的sed(这是posix版本,所以GNU sed需要
    --posix
    GNU-sed版本4.1.5
    使用
    --posix
    进行了尝试,但仍然获得了所有的行数?你是对的,我之前测试没有序列号,在codeFYI中添加了这个,接受的
    ed
    回答也会将整个文件加载到内存中。回答得好!:)执行
    -2
    的可能性很大。不久前我还和ed一起玩过,但(据我记忆所及)我最终觉得我不喜欢我需要将程序传递给stdin的事实。。但是这个答案展示了
    ed
    的一个很好的用例。我基本上喜欢
    sed
    答案,但是我认为
    sed
    不是适合这个的工具,因为它在这里的灵活性非常有限。如果OP想要删除图案上方的20条线怎么办?如果你问我,使用awk和缓冲那些n行应该被删除。这也不需要将整个文件存储在内存中,但它提供了按照您的意愿指定
    n行以删除
    的灵活性。我的意思是这就是
    awk
    的意义所在。