ファイルから読み取られた複数の値のリストをスペースで区切られた値として扱うかなり複雑なシェルスクリプトがあります。
SET1="value1 value2 value3"
for i in ${SET1}; do
...
さて、スクリプトに似た形式のリストを作成して作成したいと思います。しかし、次のようにすると(例えば):
DISCOVERED=''
DISCOVERED+=( us-east-1 )
DISCOVERED+=( us-east-2 )
DISCOVERED+=( us-west-1 )
for REGION in ${DISCOVERED} ; do
echo $REGION
done
私は何の結果も得られません。指定すると出力が得られますin ${DISCOVERED[@]}
。 SET1とDISCOVEREDで異なるデータ型を使用しているようです。
スペースで区切られた値を使用して文字列に簡単に追加できますが、クリーンアップする必要がある先行または末尾のスペースがあります。
function append_discovered {
local VALUE="$1"
if [ -z "${DISCOVERED}" ] ; then
DISCOVERED="$VALUE"
else
DISCOVERED="${DISCOVERED} ${VALUE}"
fi
}
....しかし、かなり面倒なようです。
DISCOVERED="${DISCOVERED[@]}"
出力変数を配列として扱うことはできますが、他のリストとは異なる構成を使用してこのリストを繰り返すには、その変数を再変換する必要があります。
配列でない場合、入力データのデータ型は何ですか(たとえば、上記の$ SET1)。
このリストを追加して同じデータ型を維持するためのよりきれいな方法はありますか?
答え1
SET1とDISCOVEREDで異なるデータ型を使用しているようです。
もちろん。SET1
文字列です。文字列値をスペースで区切られた複数の要素として解釈できます。DISCOVERED
一方、複数の要素を持つ配列があります。
set1='this is a string of seven words'
discovered=('this' 'is' 'an' 'array' 'with' 'seven' 'elements')
echo "$set1"
echo "${discovered[@]}"
SET1
質問の上部にあるコードの問題の1つは、すべての要素がワイルドカードで表示され拡張されることです。したがって、現在のディレクトリにあるファイルを呼び出してonebananatwo
要素が見つかると、one*
ワイルドカードone*
はに拡張されますonebananatwo
。 (これが発生しないようにするには、変数に二重引用符を使用することをお勧めします。)
スペースで区切られた値を使用して文字列に簡単に追加できますが、クリーンアップする必要がある先行または末尾のスペースがあります。
文字列が空でない場合にのみ、条件付き拡張を使用してスペースを挿入できます。
append_discovered() {
local value=$1
discovered="$discovered${discovered:+ }$value"
}
function
(誤って予約された変数と競合しないように、非標準キーワードを削除し、変数名を小文字にしました。)
次のことが起こります$discovered${discovered:+ }$value
。
$discovered
空の文字列の場合は空の${discovered:+ }
文字列も返されるため、結果は次のようになります。$value
$discovered
値がある場合は空白${discovered:+ }
が返されるため、結果は単一の空白$discovered
で構成され区切られた文字列です。$value
将来的には、文字列内のスペースで区切られた要素の代わりに配列を配列データ型として使用することを検討することをお勧めしますが、既存のスクリプトに再インストールすることは費用対効果が高く、賢明ではないかもしれません。
答え2
私のMacのbash 5.xでは、最初の構文が機能します。
DISCOVERED=''
DISCOVERED+=( us-east-1 )
DISCOVERED+=( us-east-2 )
DISCOVERED+=( us-west-1 )
echo ${#DISCOVERED[@]}
printf '"%s" ' "${DISCOVERED[@]}"
echo
出力は次のとおりです
4
"" "us-east-1" "us-east-2" "us-west-1"
DISCOVERED=''
最初の要素を空の文字列に設定するのではなく、そのステートメントからすべての配列要素を削除して最初の配列要素を展開/返しようとすると、配列が空のように見えますか?
配列変数がクリアされているか(要素なし)を確認するには、DISCOVERED=()
またはをお勧めしますunset DISCOVERED
。
以下を追加するように編集されました。
配列要素から区切られた文字列を生成するには、通常、単純な2行を使用します。この例では、' :
' を区切り文字として使用します。
printf -v SET1 '%s:' "${DISCOVERED[@]}"
SET1="${SET1%:}"
echo $SET1
(空の最初の配列要素は含まれていません。)出力:
us-east-1:us-east-2:us-west-1
組み込みプロパティを使用して配列printf
要素を繰り返し、各要素に区切り文字を追加します。 (万歳、ループを書く必要はありません!)2行目は最後の区切り文字を削除します。この方法は、空白文字を区切り文字として使用するSET1="${DISCOVERED[@]}"
場合にも機能しますが。 。