forループの前に一時的にIFSを変更する[重複]
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
ループのような複合ステートメントに対してそのようなインライン割り当てを機能させる方法があるかどうか知りたいですか?
回答
for
は予約語であるため、特別な規則に従います。
次の単語は予約語として認識されます。
!{} case do done elif else esac fi for if in then until while
この認識は、どの文字も引用されておらず、単語が次のように使用されている場合にのみ発生します。
コマンドの最初の単語
case、for、またはin以外の予約語のいずれかに続く最初の単語
(ケースのみコマンドで3番目のワードで、この場合に有効です)
forコマンドの3番目の単語(この場合はinとdoのみが有効です)
やってみたら
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
、すべて問題ありません。