Bash配列を使用してテーブルをiniファイルに変換する

Bash配列を使用してテーブルをiniファイルに変換する

次の形式の出力ファイル( "inventory.list")に問題があります。

hostname1.env1.domain   | abc  | environment1
hostname2.env1.domain   | abc  | environment1
hostname3.env2.domain   | abc  | environment2
hostname4.env2.domain   | abc  | environment2
hostname5.env1.domain   | def  | environment1
hostname6.env2.domain   | def  | environment2
(6 rows)

異なる形式で別のファイルに書き込みます。

[abc.environment1]
hostname1.env1.domain
hostname2.env1.domain

[abc.environment2]
hostname3.env2.domain
hostname4.env2.domain

[def.environment1]
hostname5.env1.domain

[def.environment2]
hostname6.env2.domain

abc役割はサーバーに割り当てられ、def各役割は複数のサーバーを持つことができるだけでなく、名前は同じですが、環境が異なる役割を持つことができます。各ホスト名を一意の[role.environment]グループに分割し、さらに行数であるファイルの最後の行を完全に削除する必要がありました(ファイルはSQLクエリの出力です)。

ファイルを読み込み、パイプとスペースを削除し、役割/環境グループを割り当て/出力できます。問題ありません。

#! /bin/bash
while IFS='| ' read -r certname role env; do
  printf '%s\n' "[""$role"".""$env""]"
done < "/tmp/inventory.list"

...役割/環境グループ名をきれいに提供します。

[abc.environment1]
[abc.environment2]
[def.environment1]
[def.environment2]

ただし、各グループ名の下の各役割/環境グループに関連付けられているホスト名を印刷する方法はわかりません。私の役割と環境フィールド(2番目と3番目のフィールド)を独自の配列に追加割り当ててから、それを参照して各一意のグループに関連付けられているホスト名を取得する必要がありますが、今はどうすればいいのかわかりません。 。誰でもアドバイスできますか?

答え1

テキストユーティリティを使用してテキストを処理します。シェルループを使用してテキストを処理する代わりに(ここではIFS=' |'あなたの場合はうまくいきます)。良い:

awk -F ' *[|] *' '
  NF == 3 {host[$2"."$3] = host[$2"."$3] $1 "\n"}
  END{for (i in host) print "[" i "]\n" host[i]}' < file

出品順序は保証されません。 GNUを使用してキーベースのソートをawk追加します。BEGIN{PROCINFO["sorted_in"] = "@ind_str_asc"}


使用しているRDBMSに応じて正しい形式で表示することもできます(例:GROUP_CONCAT存在するmysqlまたはstring_aggポストグレスから)。

まず、RDBMSクエリユーティリティに出力を後処理に適した形式で指定するように要求することもできます(たとえば、ヘッダー、フッターの削除、タブ区切り値を使用)。

答え2

連想配列を使用して、各役割と環境の証明書名を保存します。

#! /bin/bash

unset -v envs
declare -A envs

while IFS='| ' read -r certname role env; do
    envs["$role.$env"]+="$certname"$'\n' 
done < /tmp/inventory.list

for e in "${!envs[@]}" ; do
    printf '%s\n' "[$e]" "${envs[$e]}"
done

これらの部分をソートするには、キーを印刷してソートしてから、再度読み込み、関連値を出力します。

for e in "${!envs[@]}" ; do
    printf '%s\n' "$e"
done | sort | while read -r e ; do
    printf '%s\n' "[$e]" "${envs[$e]}"
done

答え3

パールマジック:

$ perl -lne '@F=split(/\s*\|\s*/); push @{$k{"$F[1].$F[2]"}},$F[0]; 
     END{foreach (keys(%k)){print "[$_]"; print join "\n",@{$k{$_}}} }' file
[abc.environment1]
hostname1.env1.domain
hostname2.env1.domain
[def.environment1]
hostname5.env1.domain
[abc.environment2]
hostname3.env2.domain
hostname4.env2.domain
[def.environment2]
hostname6.env2.domain

答え4

awkを使用する1つの方法:

$ sed 's/ //g' file | awk -F"|" '{x="["$2"."$3"]";}!(x in a){print x;a[x];}{print $1}'

関連情報