シェルスクリプトの1つに問題があります。何人かの同僚に尋ねたが、彼らは皆、(ひっかいた後)首を振っただけなので、私は答えのためにここに来た。
私の理解によると、次のシェルスクリプトは「Count is 5」を最後の行として出力します。それを除いて。 「カウントは0」と出力します。 「読み取り中」が他の種類のループに置き換えられた場合、問題なく動作します。スクリプトは次のとおりです。
echo "1"> input.data echo "2" >> input.data echo "3" >> input.data echo "4" >> input.data echo "5" >> input.data CNT = 0 cat input.data |読み取り中; do let CNT ++; echo "Counting to $ CNT" done echo "Count is $ CNT"
なぜこれが起こり、どうすればそれを防ぐことができますか?私はこれをDebian LennyとSqueezeで試しましたが、同じ結果です(つまり、bash 3.2.39とbash 4.1.5。シェルスクリプトウィザードではないことを完全に認めているので、ポインタがあれば幸いです。
引数@を参照してください Bash FAQエントリ#24: "ループに変数を設定しました。ループが終了した後、なぜ変数が突然消えるのですか?または、なぜデータをパイプできないのですか? read? " (最近アーカイブされた here )。
概要:これは、bash 4.2以降でのみサポートされています。 bashを使用している場合は、パイプの代わりにコマンド置換のようなさまざまな方法を使用する必要があります。
これは一種の「よくある」間違いです。パイプはSubShellを作成するため、while read
はスクリプトとは異なるシェルで実行されているため、CNT
変数は変更されません(パイプサブシェル内の変数のみ)。
最後のecho
をサブシェルwhile
とグループ化して修正します(修正する方法は他にもたくさんあります。これは1つの方法です。イアンとイグナシオの回答には他にもあります。)
CNT=0
cat input.data | ( while read
do
let CNT++;
echo "Counting to $CNT"
done
echo "Count is $CNT" )
長い説明:
CNT
を値0として宣言します。|
からwhile read
で開始されます。$CNT
変数は、値0でSubShellにエクスポートされます。CNT
値をカウントして5に増やします。echo
元のCNT
の値0。これは機能します
CNT=0
while read ;
do
let CNT++;
echo "Counting to $CNT"
done <input.data
echo "Count is $CNT"
代わりに、whileループの前のファイルのように、サブシェルでデータを渡してみてください。これはlainのソリューションに似ていますが、断続的なファイルが必要ないことを前提としています。
total=0
while read var
do
echo "variable: $var"
((total+=var))
done < <(echo 45) #output from a command, script, or function
echo "total: $total"