bash for ループの予期しないフィールド拡張動作

bash for ループの予期しないフィールド拡張動作

Linux/Unixでは、すべてのフィールド拡張ルールを調整するのが難しく、実験を行ってきました。以下は、私が期待したものと一致しない私の読み取りに基づいた例です。

~$ IFS=$', \t\n'
~$ for i in 1 2 3; do echo num:"$i"; done
num:1
num:2
num:3
~$ myvar=1,2,3
~$ for i in $myvar; do echo num:"$i"; done
num:1
num:2
num:3
~$ for i in 1,2,3; do echo num:"$i"; done
num:1,2,3

最終結果は私にはまったく予期せぬことでした。変数のループのbash内でのみフィールド拡張が行われるというルールをどこで見つけることができますか?

IFSbash forループが最初に設定した値を尊重しないようです。私が何かを間違って理解したのでしょうか?

答え1

フィールド分割リテラル文字列ではなく二重引用符で囲まれていないパラメータ拡張、コマンド置換、および算術拡張の結果にのみ適用されます。

を使用すると、次$myvarの効果を得ることができますglob(split(1,2,3))split(1,2,3),IFS123glob(1 2 3)123

リテラル文字列は1,2,3このプロセスの影響を受けず、単に変更されずに返されます。

答え2

次のコマンドを実行します。

LESS=+/'^ *IFS *The' man bash

読む(「強調鉱山」):


単語分割に使用されるIFS内部フィールド区切り記号拡張後そして、read組み込みコマンドを使用して行を単語に分割します。デフォルト値はです`<space><tab><newline>'

これは、拡張が行われない限り、IFSフィールド分割も起こらないことを意味します。

実際、分割は元の行で行われますが、固定メタ文字セットを使用して行われます。| & ; ( ) < > space tab

カンマ,はメタ文字ではなく、区切りには使用されません。

これこの本の第7章コマンドライン処理の詳細:

  1. コマンドを固定メタ文字セット(SPACE、TAB、NEWLINE、;、(、)、<、>、|、および&)で区切られたトークンに分割します。トークンの種類には、単語、キーワード、I/O リダイレクタ、セミコロンが含まれます。

  1. 引数、命令、および算術置換による行の部分を取得し、再び単語に分割します。今回は、手順1で設定したメタ文字の代わりに$ IFSの文字を区切り文字として使用します。

関連情報