連想配列に項目を追加するときの「無効な配列添字」エラー

連想配列に項目を追加するときの「無効な配列添字」エラー

元のクエリが完全に回答されたので、新しいクエリを開始することをお勧めします(ありがとう!)。

2つのファイルがあり、どちらもpostgresqlコマンドの出力です。最初のエントリ(/tmp/inventory.list)は元のクエリのトピックでした。Bash配列を使用してテーブルをiniファイルに変換する、@chorobaが親切に提案した配列コマンドを使用します。 2番目のファイル(/tmp/inventory2.list)の形式が最初のファイルと非常に似ていることを考えると、配列スクリプトを調整してこのファイルを同様に処理できると思いましたが、明らかに何かを混乱させました。

私の入力ファイル/tmp/inventory2.listの形式は次のとおりです。

environment1 | hostname1.environment1.domain
environment1 | hostname2.environment1.domain
environment1 | hostname3.environment1.domain
environment2 | hostname4.environment2.domain
environment2 | hostname5.environment2.domain
environment3 | hostname6.environment3.domain

グループ化された形式で別のファイルを読み書きする必要があります。

[environment1]
hostname1.environment1.domain
hostname2.environment1.domain
hostname3.environment1.domain

[environment2]
hostname4.environment2.domain
hostname5.environment2.domain

[environment3]
hostname6.environment3.domain

環境グループの間には行間隔が必要です。グループ名はアルファベット順に表示され、ホスト名はグループ内のアルファベット順にソートする必要があります。環境グループごとに複数のホスト名を持つことができますが、各グループは一度だけ表示できます。

状況を複雑にするために、入力ファイルの末尾に空行があり、postgresqlクエリでそれを省略することはできません(-tまたは--tuples-onlyは通常最後に書き込まれる行数行を削除しますが、最後の空行は削除します)これは削除する必要があり、新しい出力ファイルは作成されません。

このファイルを読み込み、正しく出力するために@chorobaの配列コマンドを調整しようとしましたが、最初のファイルでは完全に機能しましたが、調整は機能しませんでした。私は持っています:

  1 #! /bin/bash
  2
  3 unset -v envs
  4 unset -v hosts
  5 declare -A envs
  6 declare -A hosts
  7 rm -f /tmp/hosts.txt
  8
  9 while IFS='| ' read -r certname role env; do
 10     envs["$role.$env"]+="$certname"$'\n'
 11 done < /tmp/inventory.list
 12
 13 for e in "${!envs[@]}" ; do
 14 #
 15     printf '%s\n' "$e"
 16 done | sort | while read -r e ; do
 17     printf '%s\n' "[$e]" "${envs[$e]}" >> /tmp/hosts.txt
 18 done
 19
 20 while IFS='| ' read -r env certname; do
 21     hosts["$env"]+="$certname"$'\n'
 22 done < /tmp/inventory2.list
 23
 24 for f in "${!hosts[@]}" ; do
 25     printf '%s\n' "$f"
 26 done | sort | while read -r f ; do
 27     printf '%s\n' "[$f]" "${hosts[$f]}" >> /tmp/hosts1.txt
 28 done

9行から18行(および関連する3、5行)は@chorobaによって提供されたコードで、/tmp/inventory.list読み取ったファイルで完全に機能します。

20〜28行(および関連する4行と6行)は、2番目のファイル/tmp/inventory2.listを処理するために変更したものです。実行時にエラーが発生します。

 line 21: hosts["$env"]: bad array subscript

私はこの問題を数時間悩んでみましたが、私が修正したスニペットには何の問題もありません。誰でもどんなアイデアがありますか?

ベストアンサー1

入力ファイルに空白行があると述べましたが、それが/tmp/inventory2.listにある場合は問題です。

いくつかの方法で解決されました。その1つは、$env変数を使用する前にテストすることです。

[ -n "$env" ] && hosts["$env"]+="$certname"$'\n'

別の方法は、ファイルを読み取る前にファイル内のすべての文字を検索することです。

grep . inventory2.list | while IFS='| ' read -r env certname; do
  hosts["$env"]+="$certname"$'\n'
done

(「空白」行にスペースがある場合はgrepを調整してください。これに似ていますgrep [a-z]

おすすめ記事