シェルスクリプトの「for」ループ構文


190

私は以下を機能させました:

for i in {2..10}
do
    echo "output: $i"
done

これは、行の束を生成しoutput: 2output: 3その上、。

ただし、以下を実行しようとしています:

max=10
for i in {2..$max}
do
    echo "$i"
done

以下を生成します:

output: {2..10}

$ maxを文字列の一部ではなく配列のもう一方の端として扱う必要があることをコンパイラに認識させるにはどうすればよいですか?


2
どのシステムとシェルを使用していますか?どのような間抜けなシステムにはshまたはbashがありますが、seq、coreutilはありませんか?
whatsisname 2009

11
FreeBSDはサポートしていません。
Nietzche-jou

echo "$iする必要がありますecho "$i"-しかし、問題は修正されません。
デイブジャービス

小さなスタイルのニット:通常、dothenキーワードはそれぞれforとと同じ行に表示されifます。例:for i in {2..10}; do
有料オタク

回答:


233

ブレース展開、{x..y}は他の展開の前に実行されるため、可変長シーケンスには使用できません。

代わりに、ユーザーmobが述べseq 2 $max方法を使用してください

したがって、あなたの例では次のようになります:

max=10
for i in `seq 2 $max`
do
    echo "$i"
done

seqforループで数値をカウントおよびインクリメントするなどの外部コマンドを使用する十分な理由はないため、の使用は避けることをお勧めしますseq。このコマンドは、古いbashとの互換性のために残されています。組み込みコマンドは十分に高速です。for (( EXP1; EXP2; EXP3 )) ...
Miller

13
@miller for (( ... ))構文はPOSIXではないため、たとえば、Alpine Linuxなどではそのままでは機能しません。seqします。
2016

@Wernight Alpine Linuxだけではありません。#!/bin/shDebian / Ubuntuのダッシュです。
フランクリンユー

72

の算術式バージョンを試してくださいfor

max=10
for (( i=2; i <= $max; ++i ))
do
    echo "$i"
done

これはbashのほとんどのバージョンで使用でき、Bourneシェル(sh)にも対応しているはずです。


1
@Flow:うーん、#!/ bin / shを使っていくつかのシステム(LinuxとBSDベース)で試したところ、うまくいきました。bashの下、具体的には/ bin / shの下で呼び出されても、引き続き機能します。多分shのバージョンは重要ですか?古いUnixを使用していますか?
system PAUSE 2012年

8
専用のを備えているシステムはほとんどshなく、代わりに他のシェルへのリンクになっています。理想的には、このようなシェルは、呼び出されたようshです唯一の POSIX標準でこれらの機能をサポートしていますが、デフォルトでは、その余分な機能のいくつかを聞かせて。CスタイルのforループはPOSIX機能ではありませんがsh、実際のシェルによってモードになっている可能性があります。
chepner 2013

27

ループを手動でステップします。

i = 0
最大= 10
while [$ i -lt $ max]
行う
    echo "出力:$ i"
    真$((i ++))
できた

完全にPOSIXである必要がない場合は、算術forループを使用できます。

最大= 10
for((i = 0; i <max; i ++)); echo "output:$ i"; できた

または、BSDシステムでjot(1)を使用します。

for i in $(jot 0 10); echo "output:$ i"; できた

3
true $(( i++ ))すべてのケースで機能するわけではないため、ほとんどのポータブルはですtrue $((i=i+1))
フロー

セミコロンは「for((i = 0; i <max; i ++));」に含まれるべきではありません
ローガン2014

9

それを行うには複数の方法があります。

max=10
for i in `eval "echo {2..$max}"`
do
    echo "$i"
done

7
は、設定したものすべてeval評価するので、セキュリティ上のリスクがあります。を検討してから、より破壊的なものに置き換えます。maxmax="2}; echo ha; #"echo ha
chepner 2013

6
(S)彼は最大値を10に設定しました。リスクはありません。
コンラッドマイヤー

9

seqコマンドがシステムで使用できる場合:

for i in `seq 2 $max`
do
  echo "output: $i"
done

そうでない場合は、貧乏人を使用seqしてperlください:

seq=`perl -e "\$,=' ';print 2..$max"`
for i in $seq
do
  echo "output: $i"
done

それらの引用符に注意してください。


確認したところです。それはそうではないようです。
eykanal 2009

5

これは方法です:
Bash:

max=10
for i in $(bash -c "echo {2..${max}}"); do echo $i; done

上記のバッシュの方法は、のために働くだろうkshzshするとき、あまりにもbash -c置き換えられksh -cたりzsh -c、それぞれ。

注:およびでfor i in {2..${max}}; do echo $i; done動作します。zshksh


4

Cプログラミングのようにループを繰り返すことができます。

#!/bin/bash
for ((i=1; i<=20; i=i+1))
do 
      echo $i
done

2

ここでは、Mac OS Xで動作しました。

BSD日付の例、日付の増減方法も含まれています。

for ((i=28; i>=6 ; i--));
do
    dat=`date -v-${i}d -j "+%Y%m%d"` 
    echo $dat
done

2

まあ、seqシステムにコマンドをインストールしていなかったので(Mac OS X v10.6.1(Snow Leopard))、while代わりにループを使用しました。

max=5
i=1

while [ $max -gt $i ]
do
    (stuff)
done

* 肩をすくめる *何でも動作します。


2
seqは比較的新しいものです。私はそれを数ヶ月前に知りました。しかし、「for」ループを使用できます!! 「while」の欠点は、ループ内のどこかでカウンターをインクリメントするか、下向きにループすることを覚えておかなければならないことです。
システムの一時停止

1

これらはすべて機能し{1..8}、すべてPOSIXである必要があります。continueループに条件を置いても壊れません。正規の方法:

f=
while [ $((f+=1)) -le 8 ]
do
  echo $f
done

別の方法:

g=
while
  g=${g}1
  [ ${#g} -le 8 ]
do
  echo ${#g}
done

そしてもう一つ:

set --
while
  set $* .
  [ ${#} -le 8 ]
do
  echo ${#}
done

1

使用する:

max=10
for i in `eval echo {2..$max}`
do
    echo $i
done

変数の置換後に{}を再評価するには、明示的な 'eval'呼び出しが必要です。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.