bashでforループを記述する方法


回答:


103

このサイトから:

for i in $(seq 1 10);
do
    echo $i
done

10
ここで指定された範囲は包括的であることは言及する価値があります。つまり、コンソールに出力される範囲全体(1〜10)が表示されます。
ジェイミー


34

bash forは、変数(反復子)と、反復子が反復する単語のリストで構成されます。

したがって、単語のリストが限られている場合は、次の構文で入力します。

for w in word1 word2 word3
do
  doSomething($w)
done

おそらくいくつかの数値に沿って反復したいので、seqコマンドを使用して数値のリストを生成できます(たとえば1から100まで)。

seq 1 100

そして、それをFORループで使用します。

for n in $(seq 1 100)
do
  doSomething($n)
done

$(...)構文に注意してください。それはあなたが(から私たちの場合は一つのコマンドからの出力を渡すことができます、bashの振る舞いですseq(別の)for

これは、たとえば次のように、パス内のすべてのディレクトリを反復処理する必要がある場合に非常に役立ちます。

for d in $(find $somepath -type d)
do
  doSomething($d)
done

リストを生成する可能性は無限です。


2
良い答えですが、for((i = 0; i <MAX; i ++));を含めることをお勧めします。do doSomething($ i); バリアントも完了しました。$(seq 0 MAX)バリアントは実際にループを実行する前に最初に0からMAXまでのすべての数値を生成するため、これは一般にfor iよりも好ましいと思います。
mweerden 2008

30

Bash 3.0以降では、次の構文を使用できます。

for i in {1..10} ; do ... ; done

..これにより、シーケンスを拡張するための外部プログラム(などseq 1 10)の生成が回避されます。

もちろん、これにはfor(())ソリューションと同じ問題があり、bashや特定のバージョン(これが重要な場合)に結びついています。


14

bash組み込みのヘルプを試してください:


$ help for

for: for NAME [in WORDS ... ;] do COMMANDS; done
    The `for' loop executes a sequence of commands for each member in a
    list of items.  If `in WORDS ...;' is not present, then `in "$@"' is
    assumed.  For each element in WORDS, NAME is set to that element, and
    the COMMANDS are executed.
for ((: for (( exp1; exp2; exp3 )); do COMMANDS; done
    Equivalent to
        (( EXP1 ))
        while (( EXP2 )); do
            COMMANDS
            (( EXP3 ))
        done
    EXP1, EXP2, and EXP3 are arithmetic expressions.  If any expression is
    omitted, it behaves as if it evaluates to 1.


5
#! /bin/bash

function do_something {
   echo value=${1}
}

MAX=4
for (( i=0; i<MAX; i++ )) ; {
   do_something ${i}
}

これは、古いシェルでも機能する一方で、大量のカウントに対して効率的である例です。

Z=$(date) awk 'BEGIN { for ( i=0; i<4; i++ ) { print i,"hello",ENVIRON["Z"]; } }'

しかし、幸運は、内部の有益なことをやってawkどのように私はawkスクリプトでシェル変数を使うのですか?


2
以前は気づかなかったが、同様の構文が以前の回答の1つに示されている。ここでのユニークな点は、典型的なdo/ doneペアの代わりに中括弧を使用していることです。
ブレントブラッドバーン2013年

4

私は通常、標準のforループでわずかなバリアントを使用することを好みます。これをよく使用して、一連のリモートホストでコマンドを実行します。私はbashのブレース展開を利用して、非数値のforループを作成できるforループを作成しています。

例:

フロントエンドホスト1〜5およびバックエンドホスト1〜3でuptimeコマンドを実行したい。

% for host in {frontend{1..5},backend{1..3}}.mycompany.com
    do ssh $host "echo -n $host; uptime"
  done

私は通常、これを上記の読みやすいバージョンではなく、行の終わりにセミコロンを付けて1行のコマンドとして実行します。使用上の主な考慮事項は、中括弧を使用すると、文字列に挿入する複数の値を指定でき(たとえば、pre {foo、bar} post結果はprefoopost、prebarpostになります)、二重ピリオドを使用してカウント/シーケンスを許可できます(a。 .zなど)。ただし、二重ピリオド構文はbash 3.0の新機能です。以前のバージョンはこれをサポートしません。


これに関連して、もし$ host varが偶然に空行になった場合はどうなるでしょうか?それでもsshが起動します。それで、どうすればそれを回避できますか?私の場合、私は何か違うことをしているので、あなたの答えが私を助けてくれます。Gmailで新しいメッセージを確認し、見つかった場合は、送信者と件名のSMSを送信しようとしています。私の質問を読みたい場合は、「2つのBashコマンドを接続する」というラベルが付いています。
Volomike、2009年

空の$ host変数を取得するとは思いません。これは、上記の例がブレース展開を使用しているためです。forループは$ host変数を明示的に値に設定します:frontend1.mycompany.com frontend2.mycompany.com。。backend1.mycompany.comしかし、それがnull値を持つ方法を見つけた場合は、知りたいです。懸念がある場合は、条件テスト内でsshを実行できます。
terson、2009年

1

bashでのみ興味がある場合は、上記の「for((...))」ソリューションが最適ですが、すべてのuniceで機能するPOSIX SH準拠のものが必要な場合は、「expr」を使用する必要があります。 「while」、「(())」、「seq」、「i = i + 1」はさまざまなシェル間で移植性がないため


0

私はいつもこれのバリエーションを使ってファイルを処理しています...

* .log内のファイルの場合 do echo "Do stuff with:$ files"; echo "次のことをもっと行う:$ files"; 完了。

ファイルのリストの処理に関心がある場合は、ファイルの-execdirオプションを調べてください。


findの-execdirオプションのことだと思います
通知があるまで一時停止
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.