2011-09-12 1 views
11
dpkg --list |grep linux-image |grep "ii " | while read line 
do 
    arr=(${line}) 
    let i=i+1 
    _constr+="${arr[2]} " 
done 
echo $i 
echo ${_constr} 

ループ外のecho文は、期待される変数を表示しません。 変数の内容をループ外に伝播させる方法を教えてください。Bash - 変数の値をループの外部に伝播する

+6

'while'ループは別のプロセスで実行されることに注意してください。これが、変更された変数が表示されない理由です。 –

+1

プロセス置換を使用しますか? –

答えて

19

問題はパイプであり、ループではありません。このように試してください

上記のように、わかりやすくするために、グローバルをあらかじめ宣言する必要があります。

パイプは、彼のコメントでBlagovestが指摘したように、サブシェルで実行されます。 process substitution instead(これは< <(commands)の構文です)を使用すると、すべてが同じプロセスに保持されるため、グローバル変数への変更が可能です。

ところで、あなたのパイプラインは、同様

dpkg --list |grep '^ii.*linux-image' 

心配するgrepの一つ少ない呼び出しを向上させることができました。

+0

大きな説明。 +1 –

+0

説明のためにありがとう:-) – masuch

+0

bash 3.xでは、ループの最後の行は 'done <<< \' commands \ "' – Ida

3

このややにより-渡すあなたの質問は(と、それは良い質問です)、しかし、あなたは、単に使用して同じ結果を得ることができます。

_constr=($(dpkg --list | awk '/^ii.*linux-image/{print $2}')) 

($(cmd))構築物は内部コマンドの出力を使用して、bashの配列を初期化。

[[email protected]]$ echo ${_constr[*]} 
linux-image-2.6.35-22-generic linux-image-2.6.35-28-generic linux-image-generic 
[[email protected]]$ echo ${_constr[2]} 
linux-image-generic 

${#_constr[*]}を使用して要素数を取得できます。

[[email protected]]$ echo ${#_constr[*]} 
3 
+0

ありがとう:-) – masuch

+0

これは本当に正しい方法です。私はテストするDebianボックスを持っていなかったし、同じことを提案していただろう。 – Sorpigal

0

また、あなたはサブシェル内でecho文を移動することができます。サブシェルが開始位置と終了位置

dpkg --list |grep linux-image |grep "ii " | (
    let i=0 
    declare -a arr 

    while read line 
    do 
    arr=(${line}) 
    let i=i+1 
    _constr+="${arr[2]} " 
    done 
    echo $i 
    echo ${_constr} 
) 

注括弧の挿入を明示的に定義します。