grepまたはawkを使用して、パターン間のテキストブロック/行を印刷します。

grepまたはawkを使用して、パターン間のテキストブロック/行を印刷します。

私のファイルはfile.txt次のとおりです。

[NamesA]
Andreas
Alex

[NamesB]
Bernd
Bruno

[NamesC]
Casper

[NamesD]
Doris

grep次の3つの異なる出力を達成するために、これをbashスクリプトで使用または使用したいと思います。awk

  1. 出力

    [NamesB]   
    Bernd   
    Bruno
    
  2. 出力

    [NamesB]
    Bernd
    Bruno
    
    [NamesC] 
    Casper
    
  3. 出力

    [NamesD]
    Doris
    

私は試した:

grep  -oP '\[NamesB\].*?' file.txt

ただし、[NamesB]代わりに次のテキストブロックのみを取得します。私はテキストをすぐ後ろにインポートしましたが、新しい行にはインポートできませんでした。

それはすべてです。で始まる次の行を少なくともすべて得ることができれば[NamesB]それはうまくいきません。

  • したがって、1.の出力は、[NamesB]次の項目で始まり終わるすべての項目を印刷することで最も簡単になると想像できます[
  • 2番は出力1番と似ていますが、2回実行されることを想像するgrepこともできます。一度[NamesB]、その後[NamesC]

[しかし、以下がないので、3.ではこれはどのように機能しますか?そして、で始まる未知の次のブロックがあるかもしれません[

その後、コマンドはまたは[NamesB]で始まるテキストの印刷を開始し、次に開く角かっこまたは[ファイルの終わりで停止する必要があります。

PS:同様の質問を投稿して解決策を見つけましたが、全文行。この質問では、別の状況、つまり1行ではなくテキストブロックがあります。

ベストアンサー1

印刷するレコードを選択するための要件は明確ではありませんが、おそらくこれがawkでやりたいことです。

出力1、オプション1(一度に1行ずつ読みます):

$ awk '/^\[/{f=(/^\[NamesB]/)} f' file.txt
[NamesB]
Bernd
Bruno

出力1、オプション2(一度に1つの複数行レコードを読む)

$ awk -v RS= -v ORS='\n\n' -F'\n' '$1 == "[NamesB]"' file.txt
[NamesB]
Bernd
Bruno

出力2、オプション1(NamesBレコードとそれに続くレコードを印刷):

$ awk -v RS= -v ORS='\n\n' -F'\n' '$1 == "[NamesB]"{c=2} c&&c--' file.txt
[NamesB]
Bernd
Bruno

[NamesC]
Casper

出力2、オプション2(入力位置に関係なくNamesBおよびNamesCレコードを印刷):

$ awk -v RS= -v ORS='\n\n' -F'\n' '$1 ~ /^\[Names[BC]]$/' file.txt
[NamesB]
Bernd
Bruno

[NamesC]
Casper

出力3、オプション1(NamesDレコード印刷):

$ awk -v RS= -v ORS='\n\n' -F'\n' '$1 == "[NamesD]"' file.txt
[NamesD]
Doris

出力3、オプション2(名前が何であれ、入力の4番目のレコードを印刷します):

$ awk -v RS= -v ORS='\n\n' -F'\n' 'NR == 4' file.txt
[NamesD]
Doris

また、以下に関連して:

少なくとも[NamesB]で始まる次の行をすべて取得できる場合

以下はトリックを行います。

$ awk -v RS= -v ORS='\n\n' -F'\n' '$1 == "[NamesB]"{f=1} f' file.txt
[NamesB]
Bernd
Bruno

[NamesC]
Casper

[NamesD]
Doris

もちろん、さまざまな基準に基づいて出力を生成するために他の多くのスクリプトを書くことができます。正しいスクリプトは、出力するチャンクを選択するときの要件によって異なります。

おすすめ記事