Bash 打印两个图案(开始和结束)之间的最小线条集,包括这两个图案的线条 输入文件 想要的产出 笔记 从当前ANY--END--PATTERN之前的最新ANY--BEGIN--PATTERN打印 打印到最后一个Any--END--Pattern如果没有Any--BEGIN--Patternmeet 许多类似的问题,但找不到这个问题的答案 [perl] [awk/sed/grep]

Bash 打印两个图案(开始和结束)之间的最小线条集,包括这两个图案的线条 输入文件 想要的产出 笔记 从当前ANY--END--PATTERN之前的最新ANY--BEGIN--PATTERN打印 打印到最后一个Any--END--Pattern如果没有Any--BEGIN--Patternmeet 许多类似的问题,但找不到这个问题的答案 [perl] [awk/sed/grep],bash,grep,sed,awk,perl,shell,Bash,Grep,Sed,Awk,Perl,Shell,我测试的这些问题的答案打印了ccc行和/或iii。。。或者不要打印带有开始和结束图案的行。我的几次尝试都有同样的缺点和缺陷 我们可以编写一个十行脚本,但我确信有一个优雅的单行命令可以解决这个问题,但我找不到它。因此,我认为这可能是一个很好的SO问题;-) 我想知道从sed、awk、perl或任何其他在类似Unix的系统上可用的工具中可以使用哪些技巧。请提供一个小命令行,使用:,,或您认为 编辑: 只需在通过反转输入文件简化问题的注释中非常简单的命令行下划线: tac input.txt | s

我测试的这些问题的答案打印了
ccc
行和/或
iii
。。。或者不要打印带有
开始
结束
图案的行。我的几次尝试都有同样的缺点和缺陷

我们可以编写一个十行脚本,但我确信有一个优雅的单行命令可以解决这个问题,但我找不到它。因此,我认为这可能是一个很好的SO问题;-)

我想知道从
sed
awk
perl
或任何其他在类似Unix的系统上可用的工具中可以使用哪些技巧。请提供一个小命令行,使用:,,或您认为


编辑: 只需在通过反转输入文件简化问题的注释中非常简单的命令行下划线:

tac input.txt | sed -n '/END/,/BEGIN/p' | tac
但此命令行也会打印开头
(这种情况可能不会发生在其他出现类似问题的用户身上)

(此答案在中使用)

Perl来拯救

#!/usr/bin/perl
use warnings;
use strict;

my $last_end;
my @buffer;
while (<>) {
    if (/BEGIN/) {

        print @buffer[ 0 .. $last_end ] if defined $last_end;

        @buffer = $_;
        undef $last_end;
        next;
    }
    $last_end = @buffer if @buffer && /END/;
    push @buffer, $_ if @buffer;
}
$ awk '/BEGIN/{c=0; b=1} 
              {a[c++]=$0} 
      b&&/END/{for(i=0;i<c;i++) print a[i]; delete a; c=0}' file

ANY--BEGIN--PATTERN   # print 1
ddd                   # print 2
Any--END--Pattern     # print 3
ANY--BEGIN--PATTERN   # print 4
ggg                   # print 5
Any--END--Pattern     # print 6
hhh                   # print 7
Any--END--Pattern     # print 8

这应该适用于sed

sed '$b1;/BEGIN/{:1;x;s/\(BEGIN.*END[^\n]*\).*/\1/;t;x;h};H;d' file

awk
救援

#!/usr/bin/perl
use warnings;
use strict;

my $last_end;
my @buffer;
while (<>) {
    if (/BEGIN/) {

        print @buffer[ 0 .. $last_end ] if defined $last_end;

        @buffer = $_;
        undef $last_end;
        next;
    }
    $last_end = @buffer if @buffer && /END/;
    push @buffer, $_ if @buffer;
}
$ awk '/BEGIN/{c=0; b=1} 
              {a[c++]=$0} 
      b&&/END/{for(i=0;i<c;i++) print a[i]; delete a; c=0}' file

ANY--BEGIN--PATTERN   # print 1
ddd                   # print 2
Any--END--Pattern     # print 3
ANY--BEGIN--PATTERN   # print 4
ggg                   # print 5
Any--END--Pattern     # print 6
hhh                   # print 7
Any--END--Pattern     # print 8
$awk'/BEGIN/{c=0;b=1}
{a[c++]=$0}

b&&/END/{for(i=0;听着,你已经阅读了所有这些答案……根据你所阅读的内容,你有没有尝试过自己的答案?如果有,你面临什么问题?你把这个问题的措辞像是一个代码高尔夫请求。从你的经验来看,你应该知道得更清楚。;)如果你已经有了这些答案,那么你想要什么?@simbabque我可以写一个脚本来处理这个问题,但我认为使用一行命令是可能的,但我找不到:-/我认为这可能是一个好问题,不是吗?通过反转输入文件,
tac ip.txt | sed-n'/Any--END--Pattern/,/Any BEGIN Pattern/p,变得更简单了| tac
但输入文件的前两行不必要……但几乎没有一行;)@simbabque:Updated;-)比基于
perl
的答案好得多,比基于
sed
的答案更容易理解。谢谢;-)
sed '$b1;/BEGIN/{:1;x;s/\(BEGIN.*END[^\n]*\).*/\1/;t;x;h};H;d' file
$ awk '/BEGIN/{c=0; b=1} 
              {a[c++]=$0} 
      b&&/END/{for(i=0;i<c;i++) print a[i]; delete a; c=0}' file

ANY--BEGIN--PATTERN   # print 1
ddd                   # print 2
Any--END--Pattern     # print 3
ANY--BEGIN--PATTERN   # print 4
ggg                   # print 5
Any--END--Pattern     # print 6
hhh                   # print 7
Any--END--Pattern     # print 8