最初の連続パターンを無視しながらgrepから複数のパターンを検索する方法

最初の連続パターンを無視しながらgrepから複数のパターンを検索する方法

次の入力があります。間にある行で始まりabc終わるすべてを探したいのですが、mno来るabc前に再び来れば最初にmno一致する行を無視し、お互いに最も近い始まり終わるabc行だけ探せば良いという考えです。abcグループ。mno

test.txtファイルには次のデータが含まれています。

アルファベット
bbb
アルファベット
イヤ
ひどいもの
アルファベット
XXX
ひどいもの

予想出力:

アルファベット
イヤ
ひどいもの
アルファベット
XXX
ひどいもの

私は次のgrepライナーを使用しています:

grep -ozP  "(?s)(abc).\*?(mno)" test.txt

結果:

アルファベット
bbb
アルファベット
イヤ
ひどいもの
アルファベット
XXX
ひどいもの

最初の2行は出力には表示されません。grep目的の結果を得るために何を修正できるか教えてください。

答え1

この問題を解決する 1 つの方法は、tac一致検索を使用してファイルを元に戻すことです。スタートそしてmno終わりANDabc次に、反転して所望の結果を得る。私は次のようなことをしています。

$ tac test.txt | pcregrep -M 'mno(\n|.)*?abc' | tac
abc
yyy
mno
abc
xxx
mno

pcregrep(複数行フラグに使用します-M

答え2

Perlがあなたに合った場合に備えて:

#!/usr/bin/env perl
# saved lines to print out
my @out = ();
# should we save lines?
my $saving = 0;
while (<>) {
  if (/abc/) {
    if ($saving) {
      # this is the second /abc/, so dump what we were saving and start over
      @out = ($_);
    } else {
      # this is the first /abc/, so save it and start saving lines
      push @out, $_;
      $saving = 1;
    }
  } elsif (/mno/) {
    if ($saving) {
      # print what we've saved, plus this /mno/ ending line, then reset
      print @out, $_;
      @out=();
      $saving=0;
    }
  } else {
    # otherwise, save lines if we should be
    push @out, $_ if $saving;
  }
}

答え3

grep -ozP  "(?s)(abc)[^(abc)]*(mno)" 1
abc
yyy
mno
abc
xxx
mno

関連情報