如何删除当前行中的最后一个单词,但仅当下一行出现模式时?

时间:2015-02-25 12:59:18

标签: regex awk sed

该文件的内容为

some line DELETE_ME
some line this_is_the_pattern

如果 next 行中出现this_is_the_pattern,则删除当前行中的最后一个字(在本例中为DELETE_ME)。

如何使用sed或awk执行此操作?我的理解是sed比awk更适合这个任务,因为awk适合于对数据存储表格格式的操作。如果我的理解不正确,请告诉我。

5 个答案:

答案 0 :(得分:2)

$ awk '/this_is_the_pattern/{sub(/[^[:space:]]+$/, "", last)} NR>1{print last} {last=$0} END{print last}' file
some line
some line this_is_the_pattern

如何运作

此脚本使用名为last的单个变量,该变量包含文件中的上一行。总之,如果当前行包含模式,则从last中删除最后一个单词。否则,last按原样打印。

详细说明,依次采取每个命令:

  • /this_is_the_pattern/{sub(/[^[:space:]]+$/, "", last)}

    如果此行具有模式,请从最后一行中删除最后一个单词。

  • NR>1{print last}

    对于第一行之后的每一行,打印最后一行。

  • last=$0

    将当前行保存在变量last

  • END{print last}

    打印文件的最后一行。

答案 1 :(得分:1)

 awk 'NR>1 && /this_is_the_pattern/ {print t;}
      NR>1 && !/this_is_the_pattern/ {print f;}
      {f=$0;$NF="";t=$0}
      END{print f}' input-file

请注意,这将修改删除最后一个字段的任何行中的空格,将空格挤压到一个空格中。

您可以将其简化为:

awk 'NR>1 { print( /this_is_the_pattern/? t:f)}
      {f=$0;$NF="";t=$0}
      END{print f}' input-file

您可以使用以下方法解决压缩的空白问题:

awk 'NR>1 { print( /this_is_the_pattern/? t:f)}
      {f=$0;sub(" [^ ]*$","");t=$0}
      END{print f}' input-file

答案 2 :(得分:1)

您可以使用tac向后捕捉文件,以便首先看到模式。然后设置一个标志并删除您看到的下一行的最后一个单词。然后在最后,通过tac将文件反转回原始订单。

tac file | awk '/this_is_the_pattern/{f=1;print;next} f==1{sub(/ [^ ]+$/, "");print;f=0}' | tac

答案 3 :(得分:1)

使用缓冲区将前一行保留在内存中

sed -n 'H;1h;1!{x;/\nPAGE/ s/[^ ]*\(\n\)/\1/;P;s/.*\n//;h;$p;}' YourFile

使用循环但相同的概念

sed -n ':cycle
N;/\nPAGE/ s/[^ ]*\(\n\)/\1/;P;s/.*\n//;$p;b cycle' YourFile

在这两种情况下,它都会删除前一行的最后一个单词,搜索模式也会连续2行

使用2个最后读取行,测试最后一个模式,如果存在则删除单词比打印第一行,删除它并循环

答案 4 :(得分:1)

惯用awk解决方案只是保留前一行的缓冲区(或一般情况下为N行),这样您就可以测试当前行,然后相应地修改和/或打印缓冲区:

$ awk '
    NR>1 {
        if (/this_is_the_pattern/) {
            sub(/[^[:space:]]+$/,"",prev)
        }
        print prev
    }
    { prev = $0 }
    END { print prev }
' file
some line
some line this_is_the_pattern