2012-08-13 10 views
6

これはkshで動作するようになっていますが、実際にはナットを駆動しているbashでは動作しません。 うまくいけば、私が見落としていることは明らかです。bashループの配列インデックスに割り当てることが難しい

出力の各行が配列インデックスに格納される外部コマンドを実行する必要があります。

この単純化された例は、ループの配列を正しく設定したように見えますが、ループの完了後に配列の割り当てがなくなったようです。ループは外部シェルとして完全に扱われますか?

junk.txt

this is a 
test to see 
if this works ok 

testa.sh

#!/bin/bash 

declare -i i=0 
declare -a array 

echo "Simple Test:" 
array[0]="hello" 
echo "array[0] = ${array[0]}" 

echo -e "\nLoop through junk.txt:" 
cat junk.txt | while read line 
do 
    array[i]="$line" 
    echo "array[$i] = ${array[i]}" 
    let i++ 
done 

echo -e "\nResults:" 
echo "  array[0] = ${array[0]}" 
echo " Total in array = ${#array[*]}" 
echo "The whole array:" 
echo ${array[@]} 

出力

Simple Test: 
array[0] = hello 

Loop through junk.txt: 
array[0] = this is a 
array[1] = test to see 
array[2] = if this works ok 

Results: 
     array[0] = hello 
Total in array = 1 
The whole array: 
hello 

のでループで、我々は配列を代入しながら、[i]とエコーはそれを検証します。 しかし、ループの後、私は他の要素を持たない "hello"を含むarray [0]に戻ります。

bash 3,4,5のプラットフォームで同じ結果が得られます。

答えて

7

whileループはパイプラインにあるため、ループ本体内のすべての変数の割り当ては、ループが実行されるサブシェルに対してローカルです。 (私はkshはあなたがbashで問題を抱えている理由である、サブシェルでコマンドを実行していないと信じています。)の代わりに、この操作を行います。これまでに、あなたはパイプにcatを使いたいならば、

まれ
while read line 
do 
    array[i]="$line" 
    echo "array[$i] = ${array[i]}" 
    let i++ 
done < junk.txt 

を単一のファイルを別のコマンドに追加する。代わりに入力リダイレクトを使用してください。

UPDATE:あなたは、ファイルをコマンドから実行していないする必要があるため、別のオプション(利用可能な場合)は、プロセスの置換である:

while read line; do 
... 
done < <(command args ...) 

プロセス置換が利用できない場合、あなたは出力にする必要があります一時ファイルとそのファイルからの入力をリダイレクトします。

bash 4.2以降を使用している場合は、ループの前にこれらの2つのコマンドを実行することができます。この場合、whileループは最後のコマンドでパイプラインになるため、元のpipe-to-

set +m # Turn off job control; it's probably already off in a non-interactive script 
shopt -s lastpipe 
cat junk.txt | while read line; do ...; done 

UPDATE 2:ここではあなたのコマンドの出力は(各行が個別の単語であるように改行のみに基づいて単語に分割されuser1596414さんのコメント

array[0]=hello 
IFS=$'\n' array+=($(command)) 

をに基づいてループレスソリューションです)、得られたline-per-slot配列を元の配列に追加します。これはループを使用して配列を作成する場合には非常に便利です。また、おそらくPythonのリストの理解に似ていますが、少々の行単位の処理に対応するように変更することもできます。

+0

"出力の各行が配列インデックスに格納される外部コマンドを実行する必要があります。" 「猫」は単純な例でした。私はコマンドを実行して、それをループに出力し、 user1596414

+0

いくつかのオプションで更新されました。最後のもの(bashのバージョンが十分に新しいものであれば)はおそらくあなたが望むものです。 – chepner

+1

+1一時ファイルまたはbash 4.2(またはそれ以降)のオプションが機能します。 IFSを使用して空白を処理する3つ目のオプションがあり、出力を繰り返し処理する必要がない場合は、単純な配列割り当てと組み合わせることもできます。 – user1596414

関連する問題