for ループ構文

for ループ構文

なぜ

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か?2345

その理由は、実行中にジョブが評価される順序に関連しています。このコマンドを見てください

x="${i}" echo "$x"

これは何のためであるか。

  1. 変数をその値に置き換える
  2. 変数に一時値を割り当てるx
  3. 注文の実行

だからあなたは得ます

  1. x=1 echo ""(またはx=2 echo ""等)
  2. このコマンドの実行中は、x次の値に設定してください。1
  3. 注文の実行:echo ""

xこのコマンドは、値の割り当てとその値の印刷という2つのコマンドと考えることができます。ただし、シェル構文では、作成したコードが完全に合法であるため、シェルはそのような意図なしにコードを実行します。

答え2

次の2つの質問に対する回答をリクエストしました。

  1. 現在のコードが予想される出力を生成しない理由の説明を要求しました。

  2. 実際に期待される出力を生成するようにコードを書く正しい方法について質問しました。

あなたのコードを見て、なぜこのように書いたのかについての2つの可能な説明を見ることができます。

  1. 少し混乱があるかもしれませんforループの構文

  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

簡単なコマンド評価

x="$i"2番目のケースでは、コマンドプロローグの変数割り当て(割り当てなど)が、コマンド本文の変数拡張(${x}inの拡張など)のecho "${x}"前に発生すると仮定します。しかしそれは真実ではない。これを確認するにはページをご覧ください。簡単なコマンド拡張Bash マニュアルで、または簡単なコマンドのセクション内部にPOSIX仕様。両方の参照には、次の段落が含まれています。

「単純なコマンド」は、任意の順序で任意の変数割り当ておよびリダイレクトのシーケンスであり、任意にワードおよびリダイレクトが続き、制御演算子によって終了される。

与えられた単純なコマンドを実行する必要がある場合(つまり、AND-ORリストまたはケースステートメントは単純なコマンドをバイパスしません。)コマンドテキストの最初から最後まで、次の拡張、割り当て、およびリダイレクトを実行する必要があります。

  1. 次の規則に従って変数の割り当てまたはリダイレクトによって識別される単語シェル構文規則ステップ3と4の処理のために保存します。

  2. 変数の割り当てやリダイレクト以外の単語は拡張する必要があります。拡張後に残りのフィールドがある場合、最初のフィールドはコマンド名として扱われ、残りのフィールドはコマンドの引数です。

  3. リダイレクトは、次の説明に従って実行する必要があります。リダイレクト

  4. チルダ拡張、パラメータ拡張、コマンド置換、算術拡張、および引用符の削除を割り当てる前に、すべての変数割り当てを拡張する必要があります。

手順 2 ではコマンドで変数の拡張が行われますが、手順 1 では変数の割り当てが手順 3 と 4 に保存されることに注意してください。したがって、割り当てが行われるecho "${x}"まで式は拡張されます。これは、空の出力が表示される理由を説明します。echo ""x="${i}"

このトピックの詳細については、次の投稿をご覧ください。

答え3

では、Bourne演算子のzsh3番目の${var::=value}形式を使用します。ここでの割り当ては無条件です(varが設定されていないかnullの場合には該当しません)。${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}設定したx後はいつでもBourne演算子を使用できます。

for i in {1..5}; do x=; echo "${x:=$i}"; done

関連情報