如何打印开始和结束模式之间的最后一行序列?

如何打印开始和结束模式之间的最后一行序列?

这个问题的答案:

如何 grep 开始和结束模式之间的行?

不关心匹配模式之间的多个行序列。因此,例如,sed -n '/startpattern_here/,/endpattern_here/p'将打印位于这些图案出现之间的几个行序列。

但是,假设我只想打印最后的文件中的此类序列。我可以用 sed 做到这一点吗?如果没有,我想可能是 awk?还有别的事吗?

笔记:

  • 您可以假设这些序列不重叠。
  • 起始和结束图案线应该包含在输出中。
  • 假设较低复杂性模式的答案也是有效的(尽管不是最佳的)。

答案1

假设您想要完整的正则表达式测试,这可能会起作用:

awk '/startpattern_here/ {buf="";f=1}
     f{buf=buf $0 "\n"}
     /endpattern_here/ {f=0; lastcomplete=buf}
     END{printf("%s",lastcomplete)}' file.txt

这将确保只打印完整的开始-停止模式。

测试用例:

irrelevant
irrelevant
irrelevant
startpattern_here
relevant_but_dont_show_1
relevant_but_dont_show_1
relevant_but_dont_show_1
endpattern_here

irrelevant
irrelevant
 
startpattern_here
relevant_but_dont_show_2
relevant_but_dont_show_2
relevant_but_dont_show_2
endpattern_here

irrelevant
irrelevant

startpattern_here
relevant_and_show
relevant_and_show
relevant_and_show
endpattern_here

irrelevant
startpattern_here
incomplete_dont_show

结果:

startpattern_here
relevant_and_show
relevant_and_show
relevant_and_show
endpattern_here

笔记如果要抑制开始模式和结束模式的输出,只需交换规则/startpattern_here/ { ... }/endpattern_here/ { ... },即先放置“结束模式”规则,然后将“开始模式”规则放在该END规则之前。

答案2

tac 和 awk 的组合

tac file \
| awk '
   !p && /endpattern_here/   {p = 1}
    p                        {print}
    p && /startpattern_here/ {exit}
' \
| tac

答案3

前任(POSIX 编辑器)非常简单:

printf '%s\n' 1 '?END?' '?START?,.p' | ex -s file
  • 1转到文件的第一行。如果END是文件的最后一行,这是必要的。

  • ?END?向后查找(环绕文件末尾)END,从而找到它在文件中的最后一次出现。

  • ?START?,.p打印从START上一个地址到当前地址的所有内容。

下面是一个使用here-docs 而不是 的示例printf,只是为了多样性。

$ cat file
zdk
START
b12
END
kdn
START
000
111
END
START
ddd
$ ex -s file <<EOF
> 1
> ?END?
> ?START?,.p
> EOF
START
000
111
END

答案4

一种方法是简单地存储每组,用下一组覆盖它,并在到达最后时打印您保留的组:

awk '{ 
        if(/startpattern_here/){
            a=1; 
            lines=$0; 
            next
        } 
        if(a){
            lines=lines"\n"$0
        } 
        if(/end_pattern/){
            a=0
        }
    } 
    END{
        print lines
    }' file

例如,使用此测试文件:

startpattern_here
line 1
line 2
line 3
end_pattern
startpattern_here
line 1b
line 2b
line 3b
end_pattern
startpattern_here
line 1c
line 2c
line 3c
end_pattern

我得到:

$ awk '{ if(/startpattern_here/){a=1; lines=$0; next} if(a){lines=lines"\n"$0} if(/end_pattern/){a=0}} END{print lines}' file
startpattern_here
line 1c
line 2c
line 3c
end_pattern

相关内容