
どして
for i in {1..5}; do x="${i}" echo "$x"; done
出力されない
1
2
3
4
5
?
これを実行する正しい方法は何ですか?
(テスト済みfor i in {1..5}; do x=$(i) echo "$x"; done
-bash: i: コマンドが見つかりません
その他)
答え1
質問通りに答える
、、、、が
for i in {1..5}; do x="${i}" echo "$x"; done
出力されないのはなぜですか?1
2
3
4
5
その理由は、実行中に演算が評価される順序に関係しています。このコマンドを見てください
x="${i}" echo "$x"
これは
- 変数をその値に置き換える
- 変数に一時的な値を割り当てる
x
- コマンドを実行する
つまり
x=1 echo ""
(またはx=2 echo ""
、など)- このコマンドの実行中は、
x
値に設定されます1
- 次のコマンドが実行されます:
echo ""
おそらく、このコマンドは に値を割り当てx
、その値を出力するという 2 つの命令を意味していたのでしょう。しかし、シェル構文では、記述したコードは完全に合法的なので、シェルは問題なくそれを実行しました。
答え2
次の 2 つの質問に対する回答を求めました。
現在のコードが期待どおりの出力を生成しない理由について説明を求めました。
期待どおりの出力が生成されるようにコードを正しく記述する方法を尋ねました。
あなたのコードを見ると、なぜそのようにコードを書いたのか、2 つの説明が考えられます。
forループ構文
最初のケースでは、変数の割り当ての後にセミコロンがないと思われます。for ループを 1 行で記述したい場合は、ループ本体の各コマンドの後にセミコロンを置く必要があります。代わりに、次のコードを試してください。
for i in {1..5}; do x="${i}"; echo "$x"; done
別の方法としては、セミコロンの代わりに改行を使用した複数行構文を使用して for ループを記述する方法があります。
for i in {1..5}
do
x="${i}"
echo "${x}"
done
セミコロンと改行を組み合わせて使用することもできます。例:
for i in {1..5}; do
x="${i}"; echo "${x}"
done
単純なコマンドの評価
2番目のケースでは、コマンドのプロローグでの変数の割り当て(つまり割り当てx="$i"
)が、コマンド本体での変数の展開(つまり${x}
inの展開echo "${x}"
)の前に行われると想定していたと思います。しかし、実際にはそうではありません。これを確認するには、次のページを参照してください。シンプルなコマンド拡張Bashマニュアルまたは簡単なコマンドに関するサブセクションの中にPOSIX仕様これら両方の参考文献には次の一節が含まれています。
「単純コマンド」とは、任意の順序でオプションの変数割り当てとリダイレクトのシーケンスであり、オプションで単語とリダイレクトが続き、制御演算子で終了します。
与えられた単純なコマンドを実行する必要があるとき(つまり、AND-ORリストや場合ステートメントが単純なコマンドをバイパスしていない場合、次の展開、割り当て、およびリダイレクトはすべてコマンド テキストの先頭から末尾まで実行されます。
ステップ 2 ではコマンドの変数の展開が行われますが、ステップ 1 では変数の割り当てがステップ 3 と 4 まで保存されることが示されています。したがって、式は割り当てが行われる前echo "${x}"
に展開されます。これが、空の出力が得られた理由です。echo ""
x="${i}"
このトピックに関する詳細な議論については、次の投稿を参照してください。
答え3
では、のzsh
3 番目の形式である Bourne 演算子を使用し、代入は無条件になります (var が設定されていないか空の場合のみではなく)。${var::=value}
${var=value}
${var:=value}
for i in {1..5}; do echo ${x::=$i}; done
または:
for i ({1..5}) echo ${x::=$i}
でbash
:
set -o posix # so the value of x remains after eval returns
for i in {1..5}; do x=$i eval 'echo "$x"'; done
つまり、$x
その展開を含むコードが評価される時点で設定されている必要があります。
ここでのような 10 進整数値の場合は、次のようにすることもできます。
for i in {1..5}; do echo "$((x = i))"; done
または、空の文字列を${var:=value}
設定した後で、常に Bourne 演算子を使用することもできます。x
for i in {1..5}; do x=; echo "${x:=$i}"; done