
次の入力があります。間にある行で始まり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