grep
はこのタスクにはあまり適していません。1 つのツールを「上に」移動する必要があります:
sed -n '/^B/,/^E/p' infile
出力:
B
C
D
E
B
C
E
N 番目の要件に関しては、1 つのツール、つまり awk をもう一度 "上" に進めると、最も簡単だと思います:
awk '/^B/ { f = 1; n++ } f && n == wanted; /^E/ { f = 0 }' wanted=2 infile
出力:
B
C
E
フラグ f
/^B/
のときに設定されます /^E/
の場合に検出され、設定が解除されます sed 表記が機能するのとほとんど同じように発生します。 n
通過したブロックの数と f == 1 && n == wanted
の集計を保持します true の場合、デフォルト ブロックが実行されます ({ print $0 }
).
@トールの sed
コマンドを打つことはできませんが、次の perl
で script 私はあなたの質問の括弧内の部分に対処しようとします:「...(N番目の)出現...」.
使い方:
./script <start-regex> <end-regex> [N]
質問のファイルの例:
$ ./script "B" "E" < examplefile
B
C
D
E
B
C
E
$ ./script "B" "E" 2 < examplefile
B
C
D
E
F
G
B
C
E
エラーチェックなどは一切なく、スクリプトは貪欲ではありません。つまり、A B C D E E F
からです。 B C D E
のみ N=1 で grep されます。
#!/usr/bin/perl
if ($ARGV[2] != "") { $n = $ARGV[2] } else { $n = 1 }
$begin_str = $ARGV[0];
$end_str = $ARGV[1];
while(<STDIN>) {
if($_ =~ $begin_str) { $flag=1 } # beginning of match, set flag
if($_ =~ $end_str && $flag eq 1) { $i++ } # i-th occurence of end string
if($i eq $n) { # end of match after n occurences of end string
$flag=2;
$i=0;
}
if ($flag ge 1) { # append currrent line to matching part
$out.=$_;
}
if($flag eq 2) { # after detection of end of match, print complete match
print $out;
# print "---\n"; # separator after a match
$out="";
$flag=0;
}
}