@Gillesの答えは本当に素晴らしいと彼は(詳細に)複雑な問題を説明しています。
ただし、このコマンドの理由に対する答えは次のとおりです。
$ IFS=. printf "%s\n" $var
a.b.c
動作するのは、コマンドライン全体が実行される前に解析されるという単純な考えです。そして、各「単語」はシェルによって一度処理されます。
のような割り当てIFS=.は遅延します(ステップ4は最後のものです):
4.-各変数の割り当ては展開されます...
コマンドが実行される直前まで、引数内のすべての展開が最初に処理されて、この実行可能行が構築されます。
$ IFS=. printf "%s\n" a.b.c ## IFS=. goes to the environment.
a.b.c
の値は、コマンドに引数and が与えられる前に$var「古い」IFSで拡張されます。a.b.cprintf"%s\n"a.b.c
評価
遅延の1つのレベルは次によってもたらされるかもしれませんeval:
$ IFS=. eval printf "'%s\n'" \$var
a
b
c
行が解析され(1回目)、「IFS =。」次のように環境に設定されます。
$ printf '%s\n' $var
次に、これを再度解析します。
$ printf '%s\n' a b c
これを実行しました:
a
b
c
値$var(ABC)は、使用中のIFSの値が分割されます.。
環境
複雑でトリッキーな部分は、環境で有効なものです!!!
これは、Gillesの回答の最初の部分で非常によく説明されています。
追加の詳細。
このコマンドが実行されるとき:
$ IFS=. arr=($var)
IFSの値は現在の環境で保持されます、はい:
$ printf '<%s> ' "${arr[@]}" "$IFS"
<a> <b> <c> <.>
単一のステートメントのIFS。
しかし、それは避けることができます:単一のステートメントにIFSを設定する
$ IFS=. command eval arr\=\(\$var\)
$ printf '<%s> ' "${arr[@]}" "$IFS"
<a> <b> <c> <
>
IFS設定されたまま.です。最初の部分を読んだ後、それは理にかなっていますが、このQを投稿する前に、私はそれを期待していなかったでしょう。