Linuxでsedを使用して2番目のパターンがファイル内のより多くの行を繰り返す2つのパターン間の文字列を抽出する方法

Linuxでsedを使用して2番目のパターンがファイル内のより多くの行を繰り返す2つのパターン間の文字列を抽出する方法

例えば

xyz
A1
B1
C1
D1
End
End
End
X1
X2
X3
Done

xyzから終了パターンまでのすべての文字列を抽出したいと思います。したがって、出力は次のようになります

xyz
A1
B1
C1
D1
End
End
End

答え1

方法1

perl -l -0777ne 'print /^(xyz.*?^End$(?:\nEnd$)*)/ms' yourfile

布材

  • ファイルは1つの長い文字列として表示されるように読み取られ、その後適切な正規表現を使用して分割できます。この例の正規表現は次のとおりです。
    • 行の先頭でxyzを探します(必ずしもファイルである必要はありません)。
    • 一行だけで最も近い端を見つけ、できるだけ多くの連続行を探します。

方法2

perl -lne '
   next unless /xyz/ ... eof;
   last if !/End/ and $flag;
   $flag ||= 1 if /End/;
   print;
' yourfile

布材

  • ここでは、ラインごとにPerlを操作し、小さなステートマシンを設定します。
    • ファイルの範囲外の部分を拒否します。
    • 正しい範囲を入力すると、/ End /行に達するまですべての行が印刷されます。それから私たちは標識を立てました。
    • その後、/End/ではなく最初の行を見ると爆発します。

方法3

sed -e '
   /xyz/!d
   :a
      $q;N
   /\nEnd$/!ba
   :b
      n
   /End/bb
   d
' yourfile

この方法では、/xyz/から/End/までの行を累積する最初のdo-whileループ(:a)が機能します。

2番目のdo-whileループ(:b)は、次の行が/ End /になるまで行を印刷します。

方法4

sed -e '
   /xyz/,/End/!d
   H;/xyz/h;/End/!d
   :a
      $q;N
      /\(.*\)\n\1$/!{g;q;}
      s/.*\n//;H
   ba
' yourfile

このアプローチを使用して、まず正しい範囲を選択してから、その範囲データを記憶領域に保存します。 do-whileループ(:a)は、予約されたスペースに徐々に追加されるように設定されており、次の行は/ End /です。

結果

xyz
A1
B1
C1
D1
End
End
End

答え2

このpcregrep仕事は次のことをうまく行います。

pcregrep -M 'xyz(.|\n)*End' file

欲が多いので最後まで食べませんのでご注意ください終わり、その他を含む終わりS.

答え3

Perlが助けます。xyz最初の行と最後の行の間のすべての行を印刷しますEnd

 perl -ne '
     $inside = 1        if /^xyz$/;
     $seen_end = 1      if $inside && /^End$/;
     push @buff, $_     if $inside;
     print splice @buff if /^End$/ && @buff;
' input-file

最初の発生から始めて、xyzすべての行をバッファにプッシュし始めます。一度End発生したら、バッファを出力して消去します(参照接合End)、しかし後で別の行が表示される場合に備えて、行をバッファにプッシュし続けます。

答え4

アッ解決策:

awk '/xyz/,/End/{ print $0; n=NR }($0=="End" && n && NR>n && NR-n++ == 1)' file

出力:

xyz
A1
B1
C1
D1
End
End
End

  • /xyz/,/End/- 記録範囲、xyzからEnd

  • n=NR- キャプチャレコード番号(範囲一致時 - 最終的に範囲を含める最後のレコードの番号)

関連情報