web-dev-qa-db-ja.com

「for foo bar ...」の部分がない「for」ループをbashする

私は最近、それが機能し、期待していなかったために混乱したいくつかのコードを見ていました。コードはこの例に削減されます

#!/bin/bash
for var;
do
  echo "$var"
done

コマンドライン引数で実行すると、それらが出力されます

$ ./test a b c
a
b
c

これは、(私にとって)予期しないことです。 varが未定義であるため、これがエラーにならないのはなぜですか?これは「良い習慣」と見なされていますか?

26
user270650

すべてのBourneのようなシェルでin value1 value2...の部分が指定されていない場合、forループは定位置パラメーターでループします。

70年代後半のボーンシェルではすでにそうでしたが、ボーンシェルでは、;を省略する必要があります(for i doを使用することもできます(doの前に改行が必要な一部の古いashバージョンを除く)。 )。

surprisingのバリエーションを含む詳細については、 Bash forループの「do」キーワードの目的は何ですか? を参照してください。

実行:

for i
do
  something with "$i"
done

良い習慣です。通常の同等のものよりも移植性/信頼性が少し高くなります。

for i in "$@"; do
  something with "$i"
done

bourneシェル、ksh88には、いくつかの状況で問題があります(Bourneシェルの一部のバージョンで$#が0の場合(${1+"$@"}ではなく"$@"で回避できる)、または$IFSにBourneおよびksh88のスペース文字が含まれていない場合など)、またはnounsetオプションが有効で、bashを含む一部のシェルの一部のバージョンで$#が0の場合( 再度${1+"$@"}を回避策として使用 )。

28

これがデフォルトの動作です。 helpキーワードのforに記載されています。

terdon@tpad ~ $ help for
for: for NAME [in WORDS ... ] ; do COMMANDS; done
    Execute commands for each member in a list.

    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.

    Exit Status:
    Returns the status of the last command executed.

したがって、反復するリストを指定しない場合、デフォルトで、位置パラメータの配列(abおよびc$@を反復しますあなたの例)。

そして、この振る舞いは POSIXによって定義されています ですから、そうです。

20
terdon