web-dev-qa-db-ja.com

sh +配列内のすべての値を出力するためにshスクリプトで配列を使用する方法

shスクリプトでarraysを使用したい。

私の目標は、a b cという値で配列を作成し、配列内のすべての値を出力することです。

各配列の印刷に成功しましたが、配列のすべての値を印刷できませんでした。

次の例:

arrに各値を設定

n=1
eval arr$n=a
n=2
eval arr$n=b
n=3
eval arr$n=c

arrから各値を出力

n=1
eval echo \$arr$n
a
n=2
eval echo \$arr$n
b
n=3
eval echo \$arr$n
c

次に、すべての値を$arrに出力し、a b cの代わりに取得します。

n="*"
eval echo \$arr$n
{*}*

値はa b cにする必要があります。

7
maihabunash

sharrayをサポートせず、コードは配列を作成しません。 3つの変数arr1arr2arr3を作成しました。

kshのようなシェルで配列要素を初期化するには、構文array[index]=valueを使用する必要があります。配列内のすべての要素を取得するには、${array[*]}または${array[@]}を使用します。

試してください:

n=1
eval arr[$n]=a
n=2
eval arr[$n]=b
n=3
eval arr[$n]=c

n=1
eval echo \${arr[$n]}
n=2
eval echo \${arr[$n]}
n=3
eval echo \${arr[$n]}

n='*'

eval echo \${arr[$n]}
7
cuonglm

少し遅くなりましたが、理想的なshの答えがここにないので、ここで説明します。添え字が必要ない場合は、shが効果的does配列をサポートします。スペースで区切られた文字列としてそれらをサポートするだけです。それらの内容全体を印刷したり、「プッシュ」したり、問題なく反復したりできます。

これがサンプルコードの少しです:

NAMES=""
NAMES="${NAMES} MYNAME"
NAMES="${NAMES} YOURNAME"
NAMES="${NAMES} THEIRNAME"

echo 'One at a time...'
for NAME in ${NAMES}; do
    echo ${NAME};
done

echo 'All together now!'
echo ${NAMES}

どの出力:

One at a time...
MYNAME
YOURNAME
THEIRNAME
All together now!
MYNAME YOURNAME THEIRNAME

今、私はそれがサブスクリプトをサポートしていないと言いました、しかし少しのcutマジックとスペースを適切なデリミタとして使用して、あなたは絶対にそれをエミュレートすることができます。これを上記の例の一番下に追加すると:

echo 'Get the second one'
echo ${NAMES} | cut -d' ' -f2

echo 'Add one more...'
NAMES="${NAMES} TOM"

echo 'Grab the third one'
echo ${NAMES} | cut -d' ' -f3

それを実行すると、次のようになります。

Get the second one
YOURNAME
Add one more...
Grab the third one
THEIRNAME

これは私たちが期待することです!

ただし、スペースを含む文字列は問題を引き起こす可能性があり、サブスクリプトを完全に壊します。

したがって、本当により良いステートメントは次のとおりです。配列はshでは自明ではなく、スペースを含む文字列の配列の処理は困難です。それを行う必要がない場合(たとえば、デプロイ先のホスト名の配列)でも、shはこのジョブに最適なツールです。

15
hjc1710

正解は別のアプローチを見つけることであることに同意します。より良いシェルを入手するか、他のスクリプト言語(Perlやpythonなど)に切り替えるか、設計を再考してください。ただし、名前がarrで始まるすべての変数の値のリストを取得するには、次を使用できます。

set | sed -n '/^arr[^=]*=/s///p'

これはそれらを別々の行にリストします。それらすべてを1行で取得するには、

echo $(set | sed -n '/^arr[^=]*=/s///p')

これは辞書順にソートするわけではないので、arr10arr19arr1arr2の間に表示されます。 (maih1maih2、…、maih10、…、maih19という名前のファイルがある場合も同じことが起こります。)あらかじめ配列要素の数がわかっている場合これを行うには、先行ゼロを使用してこれを修正できます。例:arr01arr02、…、99までご案内します。

追伸変数の値のいずれかに改行が含まれている場合、set | sed …を使用したトリックは失敗します。

0
Scott