サブシェルから親シェルに変数を設定するにはどうすればよいですか?
a=3
(a=4)
echo $a
サブシェルの重要な点は、呼び出しセッションにdoes n'tが影響することです。 bashでは、サブシェルは子プロセスであり、他のシェルは異なりますが、サブシェルの変数設定は呼び出し元に影響しません。定義により。
サブシェルが必要ですか?グループが必要な場合は、中括弧を使用します。
a=3
{ a=4;}
echo $a
4
(そのスペースに注意してください)。または、変数値をstdoutに書き込み、呼び出し元でキャプチャします。
a=3
a=$(a=4;echo $a)
echo $a
バックティックを使用しないでください ``、それらは非推奨であり、読みにくい場合があります。
Gdb-bash-variableハックがあります:
gdb --batch-silent -ex "attach $$" -ex 'set bind_variable("a", "4", 0)';
ただし、親スコープだけでなく、常にグローバルスコープ内の変数を設定します
あなたはしません。サブシェルは親の環境にアクセスできません。 (少なくともBashが提供する抽象化の範囲内では、gdb
を使用したり、スタックを破壊したりするなどして、そのようなアクセスを密かに取得することができます。しかし、お勧めしません。)
1つの代替方法は、サブシェルが割り当てステートメントを、その親が読み取る一時ファイルに書き込むことです。
a=3
(echo 'a=4' > tmp)
. tmp
rm tmp
echo "$a"
問題がwhileループに関連している場合、これを修正する1つの方法は、Process Substitutionを使用することです。
var=0
while read i;
do
# perform computations on $i
((var++))
done < <(find . -type f -name "*.bin" -maxdepth 1)
親スクリプトから呼び出されたスクリプトの変数を変更するには、「。」が前に付いたスクリプトを呼び出すことができます。
a=3
echo $a
. ./calledScript.sh
echo $a
calledScript.shで
a=4
期待される出力
3
4
サブシェルで値を出力し、呼び出し元スクリプトの変数にサブシェル出力を割り当てることができます。
# subshell.sh
echo Value
# caller
myvar=$(subshell.sh)
サブシェルがさらに出力する必要がある場合、変数値と他のメッセージを異なる出力ストリームにリダイレクトすることでそれらを分離できます。
# subshell.sh
echo "Writing value" 1>&2
echo Value
# caller
myvar=$(subshell.sh 2>/dev/null) # or to somewhere else
echo $myvar
または、サブシェルで変数の割り当てを出力し、呼び出し元スクリプトでそれらを評価し、ファイルを使用して情報を交換しないようにすることができます。
# subshell.sh
echo "a=4"
# caller
# export $(subshell.sh) would be more secure, since export accepts name=value only.
eval $(subshell.sh)
echo $a
私が考えることができる最後の方法は、終了コードを使用することですが、これは整数値の交換のみ(および制限された範囲内)をカバーし、終了コードの解釈の規則を破ります(成功する場合は0、それ以外の場合は0以外)。
すべてのioをパイプに適用してファイルハンドルを使用できない限り、基本的な変数の更新は$(command)およびその他のサブプロセス内では不可能です。
ただし、通常のファイルは、通常の順次処理のためのbashのグローバル変数です。注:競合状態のため、この単純なアプローチは並列処理には適していません。
次のようなset/get/default関数を作成します。
globalVariable() { # NEW-VALUE
# set/get/default globalVariable
if [ 0 = "$#" ]; then
# new value not given -- echo the value
[ -e "$aRam/globalVariable" ] \
&& cat "$aRam/globalVariable" \
|| printf "default-value-here"
else
# new value given -- set the value
printf "%s" "$1" > "$aRam/globalVariable"
fi
}
「$ aRam」は、値が保存されるディレクトリです。私は速度と揮発性のためにラムディスクであることが好きです:
aRam="$(mktemp -td $(basename "$0").XXX)" # temporary directory
mount -t tmpfs ramdisk "$aRam" # mount the ram disk there
trap "umount "$aRam" && rm -rf "$aRam"" EXIT # auto-eject
値を読み取るには:
v="$(globalVariable)" # or part of any command
値を設定するには:
globalVariable newValue # newValue will be written to file
値を設定解除するには:
rm -f "$aRam/globalVariable"
アクセス機能の唯一の本当の理由は、存在しないファイルを指定するとcatがエラーになるため、デフォルト値を適用することです。他のget/setロジックを適用することも役立ちます。それ以外の場合は、まったく必要ありません。
猫の存在しないファイルエラーを回避するreadい読み取りメソッド:
v="$(cat "$aRam/globalVariable 2>/dev/null")"
この混乱のクールな機能は、プログラムの実行中に別のターミナルを開いてファイルの内容を調べることができることです。