次の内容を含むテキストファイルがあります。
$ 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"
tr
すべてを一行に入れます- 最初の項目は
sed
各セクションの前にラップされます。 grep
お好みの線(部分)を切り取ります。- 2番目に
sed
[]部分が削除されます。 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