sed/awk を使用した YAML ファイルのコンテンツのフィルタリング

sed/awk を使用した YAML ファイルのコンテンツのフィルタリング

次の内容を含むテキストファイルがあります。

$ cat hosts.yml
[prod_env]
foo.example.com
bar.example.com
[stage_env]
foo_stage.example.com
bar_stage.example.com
[dev_env]
foo_dev1.example.com
dev2_bar.example.com

Bashの[prod_env]ファイルの下にリストされているホストをフィルタリングしたいと思います。私は限られた知識でsed、awk、およびgrepを試しましたが、フィルタリングする方法がわかりません。

例:prod_envとdev_envの下のホストを印刷したいと思います。したがって、最終出力は次のようになります。

foo.example.com 
bar.example.com 
foo_dev1.example.com 
dev2_bar.example.com

答え1

解決策sed

sed -nEe '/\[(prod|dev)_env]/!d;N;:loop' -e 's/.*\n//;${p;d;};N;P;/\n\[/D;bloop' hosts.yml
  • /\[(prod|dev)_env]/!d[prod_env]検索[dev_env]または検索されるまですべての行を削除
  • N;:loop次の行を追加して繰り返し開始
  • ループ内の2行のうち最初の行を削除します。s/.*\n//これ[...env]は、縮小または最後のループサイクルですでに印刷されているためです。
  • ${p;d;}印刷中に最後の行に達すると、残りの行が印刷されます。
  • N;P次の行を追加して現在の行を印刷する
  • /\n\[/D次の行がで始まることを確認してください[。この場合、バッファの最初の行(印刷された)を削除でき、[その行から始まります。
  • bloopそうでなければループ

バッファに次の行を追加し、前の行を印刷して削除するのではなく、1行ずつ実行できますが、再起動できないため、別のループが必要です。D

答え2

(Macでは)次のことができます。

tr "\n" "\t" < hosts.yml | sed $'s%\t\\[%\\\n\[%g' | grep 'prod\|dev' | sed $'s%.*\]\\\t%%g' | tr "\t" "\n"
  1. trすべてを一行に入れます
  2. 最初の項目はsed各セクションの前にラップされます。
  3. grepお好みの線(部分)を切り取ります。
  4. 2番目にsed[]部分が削除されます。
  5. tr各行が1つのホスト名を持つように、行は末尾に折り返されます。

答え3

awk 'BEGIN{RS="[";FS="]\n"} 
     $1 ~/(prod|dev)_env/ {print $2}' ex1

答え4

GNU sed以下の方法を使用してこれを実行できます。

$ sed -nEe '
   /\[/!{H;$!d;}
   x;1!s/^\[(prod|dev)_env]\n//p
' hosts.yml

関連情報