grep、sed、awk、perl:セクション内のIDに基づいてファイルからセクションを取得する

grep、sed、awk、perl:セクション内のIDに基づいてファイルからセクションを取得する

次の形式のファイルがあるとします。

(lots of sections...)

SECTION foo
    keyA=valA
    ...
ENDSECTION

(lots of sections...)

sedを使用してその部分を抽出できますsed -nE /^SECTION foo$/,/^ENDSECTION$/p。私の問題は、フォーマットが次のように変更されたときに発生します。

(lots of sections...)

SECTION
    keyA=valA
    id=foo
    ...
ENDSECTION

(lots of sections...)

一般的なツール(grep、sed、awk、perl、bash)を使用してこの部分を取得する方法はありますか?

ベストアンサー1

これは、文書の形式がどのように「うまく構成されているか」によって多少異なります。それぞれSECTIONに一致するものがあると確信している場合は、次のENDSECTIONコードがawk機能します。ただし、「一行」とは呼びません(最初からこれが可能かどうかはわかりません)。

awk -v pat='id=foo' '/^SECTION/{n=f=0; delete buf;} \
 {buf[++n]=$0; if (index($0,pat)) f=1} \
 /^ENDSECTION/ {if (f) for (i=1;i<=n;i++) print buf[i]}' input.txt
  • 検索パターンはユーザーが指定したとおりに適用されますpat(ただし、現在の形式では正規表現ベースの検索ではなく固定文字列検索のみを実行します)。
  • SECTION(またはキーワード)で始まる行が見つかると、フラグf(「発見」を意味)と行カウンタがnゼロに初期化されます。また、セクションが完了するまで印刷するかどうかを判断できないため、セクション全体をバッファリングする必要があるため、バッファ変数を消去しますbuf
  • すべての行(この例では空の行を含む)に対して行カウンタがnインクリメントされ、その行が配列変数に追加されますbuf。このフラグは、行でパターンが見つかるとf設定されます1
  • ENDSECTIONキーワードが行の先頭にあり、フラグがある場合は、バッファをf11行ずつ印刷してその部分を出力します。

すべての部分が空白行で区切られていることを確認できれば、この回答少ないコードでこれを行う方法の正しい方向を知ることができますが、これが保証されていないと、「ショートモード」アプローチはawk機能しません。

また、この提案は、タスクを実行するために必要な最小限の事項です。空白行をスキップしたり、他の健全性チェック要件を満たす場合は、コードがかなり長くなる可能性があります。

おすすめ記事