開始パターンと終了パターンの間のパターンに基づいて開始パターンと終了パターンの間のテキストを取得する

開始パターンと終了パターンの間のパターンに基づいて開始パターンと終了パターンの間のテキストを取得する

私はstartStrケースとの間のすべてを得るために努力しています。私は使用方法とその間に発生するすべてのイベントを理解しています。発生事例を1つだけ制限する方法がわかりません。endStrbbbstartStrendStrsedbbb

入力例:

fff
startStr
aaa
bbb
ccc
endStr
xxx
yyy
startStr
ddd
endStr
ddd
bbb

希望の出力:

startStr
aaa
bbb
ccc
endStr

これが私が持っているものです:

$ sed -n -e '/startStr/,/endStr/ p' sample.txt
startStr
aaa
bbb
ccc
endStr
startStr
ddd
endStr

答え1

最初のstartStr...については、endStr次が含ま/bbb/れます。

 sed -n '/startStr/ {:n; N; /endStr/ {/\n[^\n]*bbb[^\n]*\n/ {p; q}; b}; bn}'

または

sed -n '/startStr/ {:n; N; /endStr/ {/\nbbb\n/ {p; q}; b}; bn}'

正規表現でない場合は、bbb正確に必要な文字列です(最初からから\n)。

説明する

住所の場合/startStr/:

  • :nラベル設定
  • 次の行を読むN
  • 一致していることを確認してください/endStr/
    • これが本当なら、/\nbbb\n/私たちが読んだこのブロックで発生を確認してください。
      • ある場合は、{p; q}「印刷と終了」を実行します。
      • それ以外の場合は、b「このブロックをスローして次のブロックの検索を開始します」を実行します。
  • ブロックの終わりでない場合に移動します:n。つまり、読み続けます。

答え2

pcregrepこの仕事に関する私のアドバイスは次のとおりです。

pcregrep -M 'startStr(.|\n)*?bbb(.|\n)*?endStr' sample.txt

オプションを使用すると、貪欲な演算子なしで-M複数行のパターンを一致させることができます。*?残りは明確でなければなりません。

答え3

以前に一致したブロックがstartStr...endStrないブロックを含むように入力サンプルを変更します。bbb

$ cat ip.txt 
startStr
foo
bar
endStr
fff
baz
startStr
aaa
bbb
ccc
endStr
xxx
yyy
startStr
ddd
endStr
ddd
bbb


awk解決策

awk '/startStr/{f=1; m=0; buf = $0; next}
     /bbb/ && f{m=1}
     f{buf = buf ORS $0}
     /endStr/ && f{f=0; if(m==1)print buf}
    ' ip.txt
  • /startStr/{f=1; m=0; buf = $0; next}ブロックの開始を示すフラグの設定、一致のクリア、バッファの初期化、次の行に移動
  • /bbb/ && f{m=1}行にが含まれている場合は一致を設定しますbbb。外部f一致を防ぐために使用されます。bbbstartStr...endStr
  • f{buf = buf ORS $0}フラグが設定されるたびに入力行を累積します。
  • /endStr/ && f{f=0; if(m==1)print buf}ブロックの最後に一致するものが見つかった場合は、バッファを印刷します。


一行で:

$ awk '/startStr/{f=1; m=0; buf = $0; next} /bbb/ && f{m=1} f{buf = buf ORS $0} /endStr/ && f{f=0; if(m==1)print buf}' ip.txt 
startStr
aaa
bbb
ccc
endStr


入力ファイル全体を吸収することでより簡単なperl解決策 - 同様のブロックがないと仮定しますstartStr...startStr...endStr(例:first startStrなしendStr)

$ perl -0777 -ne '(@m) = /startStr.*?endStr\n/gs; print grep { /bbb/ } @m' ip.txt 
startStr
aaa
bbb
ccc
endStr

答え4

sed -n -e '/startStr/,/bbb/p;/bbb/,/endStr/p' /path/to/input

関連情報