forループの前に一時的にIFSを変更する[重複]

Aug 16 2020

SHELL変数の割り当てがコマンドの直前に行われることを許可していることを知っていますIFS=":" read a b c d <<< "$here_string"

私が疑問に思っていたのは、ループなどの複合ステートメントで実行すると、そのような割り当てが機能しないのでしょうか。のようなものを試しIFS=":" for i in $PATH; do echo $i; doneましたが、構文エラーが発生します。私はいつでものようなoldIFS="$IFS"; IFS=":"; for....; IFS="$oldIFS"ことをすることができましたが、forループのような複合ステートメントに対してそのようなインライン割り当てを機能させる方法があるかどうか知りたいですか?

回答

3 Quasímodo Aug 16 2020 at 21:12

forは予約語であるため、特別な規則に従います。

次の単語は予約語として認識されます。

!{} case do done elif else esac fi for if in then until while

この認識は、どの文字も引用されておらず、単語が次のように使用されている場合にのみ発生します。

  • コマンドの最初の単語

  • casefor、またはin以外の予約語のいずれかに続く最初の単語

  • (ケースのみコマンドで3番目のワード、この場合に有効です)

  • forコマンドの3番目の単語(この場合はindoのみが有効です)

やってみたら

IFS=":" for i in $PATH; do echo $i; done

、上記のルールにより、forキーワードはコマンドの最初の単語ではないため、ループではありません。しかし、あなたの意図はで達成することができます

IFS=: printf '%s\n' $PATH

$PATH:期待どおりに単語が分割されprintf、結果の各単語は、の後に改行が続きます。


あなたはこの有効なアプローチに精通しているかもしれません:

while IFS= read -r line; do

whileはコマンドの最初の単語であり、IFS割り当てはに適用されるためread、すべて問題ありません。