1. ホーム
  2. shell

sed、AWK、Perlで)2つのパターンの間の行を、包括的または排他的に表示するには?

2023-10-02 09:01:58

質問

以下のようなファイルがあり、与えられた2つのパターンの間の行を表示したい。 PAT1PAT2 .

1
2
PAT1
3    - first block
4
PAT2
5
6
PAT1
7    - second block
PAT2
8
9
PAT1
10    - third block

私が読んだのは awk/sed で複数回発生する可能性のある 2 つのマーカーパターンの間の行を選択する方法 を読みましたが、私はこのパターンを含むか含まないか、すべての可能な組み合わせを見てみたいと思っています。

2 つのパターンの間にあるすべての行を表示するにはどうしたらよいでしょうか。

どのように解決するのですか?

PAT1とPAT2の間の行を印刷する

$ awk '/PAT1/,/PAT2/' file
PAT1
3    - first block
4
PAT2
PAT1
7    - second block
PAT2
PAT1
10    - third block

あるいは、変数を用いて

awk '/PAT1/{flag=1} flag; /PAT2/{flag=0}' file

これはどのように機能するのでしょうか?

  • /PAT1/ は、このテキストを持つ行にマッチし、さらに /PAT2/ と同様です。
  • /PAT1/{flag=1}flag が設定されると、テキスト PAT1 が行内に見つかった場合。
  • /PAT2/{flag=0} をアンセットします。 flag というテキストがある場合 PAT2 が行内に見つかった場合。
  • flag は、デフォルトの動作であるパターンで print $0 : もし flag が 1 ならば、その行が表示される。このようにすると、以下の時刻から発生したすべての行が表示される。 PAT1 が発生した時点から、次の PAT2 が表示されます。の最後のマッチからの行も表示されます。 PAT1 に最後にマッチした行からファイルの終わりまで表示します。

PAT1とPAT2の間の行を印刷 - PAT1とPAT2は含まない

$ awk '/PAT1/{flag=1; next} /PAT2/{flag=0} flag' file
3    - first block
4
7    - second block
10    - third block

これは next を含む行をスキップするために PAT1 を含む行をスキップさせることで、これが印刷されないようにします。

この next の呼び出しは、ブロックを入れ替えることで削除することができます。 awk '/PAT2/{flag=0} flag; /PAT1/{flag=1}' file .

PAT1とPAT2の間の行を印刷する - PAT1を含む

$ awk '/PAT1/{flag=1} /PAT2/{flag=0} flag' file
PAT1
3    - first block
4
PAT1
7    - second block
PAT1
10    - third block

を配置することで flag を最後に記述することで、PAT1またはPAT2のどちらかに設定されたアクションをトリガーします:PAT1に印刷し、PAT2に印刷しない。

PAT1 と PAT2 の間の行を印刷 - PAT2 を含む

$ awk 'flag; /PAT1/{flag=1} /PAT2/{flag=0}' file
3    - first block
4
PAT2
7    - second block
PAT2
10    - third block

を配置することで flag を置くことで、先に設定されたアクションをトリガーし、終了パターンを印刷しますが、開始パターンは印刷しません。

PAT1 と PAT2 の間の行を印刷します - 最後の PAT1 からファイルの終わりまでの行は、他の PAT2 が発生しない場合は除外されます。

これは Ed Morton による解決策 .

awk 'flag{
        if (/PAT2/)
           {printf "%s", buf; flag=0; buf=""}
        else
            buf = buf $0 ORS
     }
     /PAT1/ {flag=1}' file

ワンライナーとして

$ awk 'flag{ if (/PAT2/){printf "%s", buf; flag=0; buf=""} else buf = buf $0 ORS}; /PAT1/{flag=1}' file
3    - first block
4
7    - second block

# note the lack of third block, since no other PAT2 happens after it

これは、PAT1が見つかった瞬間から、選択されたすべての行をバッファに保持します。そして、PAT2が見つかるまでは、次の行で満たされ続けます。その時点で、保存されている内容を表示し、バッファを空にします。