COUNTER
誰かが(私の観点から)次のコードで変数の奇妙な動作を説明しますか?
#!/bin/bash
COUNTER=0
function increment {
((COUNTER++))
}
function report {
echo "COUNTER: $COUNTER ($1)"
}
function reset_counter {
COUNTER=0
}
function increment_if_yes {
answer=$1
if [ "$answer" == "yes" ]
then
increment
fi
}
function break_it {
echo -e "maybe\nyes\nno" | \
while read LL
do
increment_if_yes $LL
done
}
report start # counter should be 0
increment
report one
increment_if_yes yes
report two
increment_if_yes no
report "still two"
reset_counter
report reset
break_it
report "I'd expect one"
私はそれがスクリプトの終わりにCOUNTER
なりたいのですが、それは次のようになります:1
0
$ ./broken_variable.sh
COUNTER: 0 (start)
COUNTER: 1 (one)
COUNTER: 2 (two)
COUNTER: 2 (still two)
COUNTER: 0 (reset)
COUNTER: 0 (I'd expect one)
ベストアンサー1
OPの現在のコードはで期待どおりに機能し、ksh
他のシェルでも機能できますが、機能しない可能性がありますbash
。
ループがbreakit()
子プロセス内で実行されるようにします。これは、最終的にwhileループのすべての関数呼び出しが子プロセス内でも実行されることを意味します。echo ... | while ...
while
子プロセス(while
この場合はループ)はコピー変数COUNTER
なので、子プロセスの変更は次のようにのみCOUNTER
適用されます。コピー変わりやすい。子プロセスが終了するとコピー紛失しましたCOUNTER
。制御権が親プロセスに返された場合(元)、COUNTER
変数は子プロセスを開始する前と同じ値を持ちます。
while
目的の動作を達成するには、ループが親プロセスで実行されていることを確認する必要があります。プロセス置換を使用する1つの方法:
while read LL
do
increment_if_yes "$LL"
done < <( echo -e "maybe\nyes\nno" )