2016-12-08 4 views
1

bashで連想配列を書きたいと思っています。私は配列のために必要な入力を生成するコマンドのパイプラインを持っています。ここでbash:コマンドパイプラインからグローバル変数にアクセスする

は、最小限の/おもちゃの例です。この例mapping

declare -A mapping 
seq 10 | while read i; do 
    key="key_$i" 
    val="val_$i" 
    echo "mapping[$key]=$val" 
    mapping["${key}"]="${val}" 
done 

echo "${mapping["key_1"]}" 
echo "${mapping["key_2"]}" 

while内で変更されますが、これらの変更は、グローバル名前空間に反映されません。これは、whileが別のサブシェルの内部で動作するためです。したがって、名前空間は分岐しています。

は(私が示唆するもの)サブシェルの問題を避けるために、私は次のを思い付いた:

declare -A mapping 
while read i; do 
    key="key_$i" 
    val="val_$i" 
    echo "mapping[$key]=$val" 
    mapping["${key}"]="${val}" 
done < <(seq 10) 

echo "${mapping["key_1"]}" 
echo "${mapping["key_2"]}" 

whileループがで左つつ、生成部は、明示的に、サブシェルに入りますトップレベルのみ。建設はうまくいく。

私の質問は:私の目標を達成するためのより良い方法はありますか?そして、サブシェルに関する私の提案は正しいですか?もしそうなら、なぜbashが最初のケースではサブシェルを使用しますが、2番目のケースでは使用しませんか?

EDIT:もう少し掘り下げた後、質問はほとんどthis oneの複製です。問題を処理するためのオプションの良いリストは、これはあなたの2番目のコードスニペットよりも良い方法ですが、最初のものを解決する方法は、右のパイプの後にサブシェル{ ... }を使用することであるかどうかわからないhttp://mywiki.wooledge.org/BashFAQ/024

+1

パイプコマンドは、右側(ループ)がそのサブシェルへのすべての変更を終了すると、別のサブシェルで両側を実行します。 <<(command)、サブシェルでコマンドを開き、ループがメインループにあるので、whileループからの変更を保持します。 – 123

答えて

1

で見つけることができ:

declare -A mapping 
seq 10 | { 
    while read i; do 
     key="key_$i" 
     val="val_$i" 
     echo "mapping[$key]=$val" 
     mapping["${key}"]="${val}" 
    done 

    echo "${mapping["key_1"]}" 
    echo "${mapping["key_2"]}" 
} 
+0

興味深いですが、すべての 'マッピング 'の使用法をサブシェルの内側に置くことができる場合にのみ、明らかに使用可能です。 –

関連する問題