web-dev-qa-db-ja.com

bash forループで変数を使用する方法

Bash forループで変数を使用する方法標準のforループを使用する場合、期待どおりに動作します

for i in {0..3}
do
   echo "do some stuff $i"
done

これは正常に機能します。 0〜3を含めて4回ループし、メッセージを出力して最後にカウントを入れます。

do some stuff 0
do some stuff 1
do some stuff 2
do some stuff 3

次のforループで同じことを試みると、文字列に等しいように見えますが、これは私が望んでいるものではありません。

length=3
for i in {0..$length}
do
   echo "do something right $i"
done

出力:

do something right {0..3}

私はもう試した

for i in {0.."$length"} and for i in {0..${length}} (both output was {0..3})

そして

for i in {0..'$length'} (output was {0..$length})

そして、彼らは両方とも私が必要とすることをしません。うまくいけば誰かが私を助けることができます。 forループに関するbashの専門家の支援に感謝します。

29
Classified

1つの方法はevalを使用することです:

for i in $( eval echo {0..$length} )
do
       echo "do something right $i"
done

length=;lsまたはlength=; rm *を設定するとどうなりますか(後者は試さないでください)。

安全にseqを使用:

for i in $( seq 0 $length )
do
       echo "do something right $i"
done

または、Cスタイルのforループを使用できますが、これも安全です。

for (( i = 0; i <= $length; i++ )) 
do 
       echo "do something right $i"
done
39
perreal

Bashでは、ブレースの展開はfirstステップであるため、その時点で、$lengthは置換されません。

Bashのマンページには次のように明記されています。

シーケンス式の形式は{x..y [.. incr]}で、xとyは整数または単一文字 ...です。

以下を使用するなど、多くの可能性があります。

pax> for i in $(seq 0 $length) ; do echo $i ; done
0
1
2
3

ただし、lengthが大きい場合は、コマンドラインが大きくなる可能性があります。

別の方法は、Cのような構文を使用することです。

pax> for (( i = 0; i <= $length; i++ )) ; do echo $i; done
0
1
2
3
7
paxdiablo

ブレースの置換は他の置換の前に実行されるため、evalまたはseqなどのサードパーティツールを使用する必要があります。

Evalの例:

for i in `eval echo {0..$length}`; do echo $i; done

この情報は、実際にman bash

シーケンス式は{x..y [.. incr]}、xとyは整数または単一文字の形式を取り、オプションの増分であるincrは整数です。 [...]

ブレース展開は他の展開の前に実行され、他の展開に特殊な文字は結果に保存されます。これは厳密にテキストです。 Bashは、展開のコンテキストまたは中括弧間のテキストに構文解釈を適用しません。

3
nemo