bashスクリプトでIFS = $ '\ n'の意味は何ですか?


163

bashシェルスクリプトの先頭には、次の行があります。

IFS=$'\n'

この記号のコレクションの背後にある意味は何ですか?


3
unix.stackexchange.com/questions/26784/understanding-ifsおよびそれが引用する質問も参照してください。
ジル

vim構文は、これをエラーとして強調しています。修正しますか?
-theonlygusti

IFS=$'\n'はバシズムです(+他のシェル、ANSI-C引用を使用、回避策についてはstackoverflow.com/questions/10748703/…を
ペビック

回答:


199

IFS「内部フィールド区切り文字」を表します。これは、単語の分割方法、つまり単語の境界を認識する方法を決定するためにシェルによって使用されます。

これをbashのようなシェルで試してみてください(他のシェルでは、zshなど、これを異なる方法で処理できます)。

mystring="foo:bar baz rab"
for word in $mystring; do
  echo "Word: $word"
done

のデフォルト値IFSは空白文字で構成されます(正確には、スペース、タブ、改行)。各文字は単語の境界にすることができます。したがって、デフォルト値のIFS場合、上記のループは次のように出力されます。

Word: foo:bar
Word: baz
Word: rab

言い換えれば、シェルは空白が単語境界であると考えます。

ここでIFS=:、ループを実行する前に設定してみてください。今回の結果は次のとおりです。

Word: foo
Word: bar baz rab

これで、シェルmystringも単語に分割されますが、コロンは単語境界としてのみ処理されます。

の最初の文字IFSは特別です:特別な$*変数を使用するときに、出力内の単語を区切るために使用されます(Advanced Bash Scripting Guideから取られた例では、そのような特別な変数に関する詳細情報も見つけることができます):

$ bash -c 'set w x y z; IFS=":-;"; echo "$*"'
w:x:y:z

と比較:

$ bash -c 'set w x y z; IFS="-:;"; echo "$*"'
w-x-y-z

どちらの例でも、シェルはすべての文字:-および;を単語境界として処理することに注意してください。変更されるのは、の動作だけです$*

知っておくべきもう1つの重要なことは、いわゆる「IFSホワイトスペース」の処理方法です。基本的に、IFS空白文字が含まれるとすぐに、先頭と末尾の空白が文字列から削除されてから処理され、一連の連続した空白文字もフィールドを区切ります。ただし、これは実際にに存在する空白文字にのみ適用されIFSます。

たとえば、のは、文字列を見てみましょう"a:b:: c d "(末尾のスペースと2つのスペース文字間cd)。

  1. IFS=:、それには次の4つのフィールドに分割されます:"a""b"""(空の文字列)と" c d "(再び、二つの空間の間cd)。最後のフィールドの先頭と末尾の空白に注意してください。
  2. ではIFS=' :'、それは5つのフィールドに分割されます:"a""b"""(空の文字列)、"c"および"d"。どこにも先頭および末尾の空白はありません。

2番目の例では、複数の連続した空白文字が2つのフィールドを区切るのに対し、複数の連続したコロンは空白文字ではないため、どのように区切られているかに注意してください。

IFS=$'\n'つまりksh93によってもサポートされている構文bashzshmkshとFreeBSD sh(すべてのシェル間の変動を有します)。bashのマンページを引用:

$ 'string'という形式の単語は特別に扱われます。単語は「string」に展開され、ANSI C標準で指定されているように、バックスラッシュでエスケープされた文字が置き換えられます。

\nは改行のエスケープシーケンスであるため、IFS最終的に単一の改行文字に設定されます。


3
これは良いことですが、私の意見では、bashスクリプトガイドなどではなく、POSIX仕様を読んで理解する方がはるかに良いでしょう。主に、そのようなリンクで利用可能な情報は重要な点で欠けています。とにかく、シェルの分割に関する2つの重要なポイント、つまりグロビングとIFSホワイトスペースを見逃しています。
mikeserv

@mikeservありがとう、IFSホワイトスペースに関する情報を追加しました。それについて知らなかった。:)
Tblue

4
関連性はunset IFSそれほど高くありませんが、好奇心が強い場合は、シェルの動作をどのように非常に異なるものにするかを調べてくださいIFS=。また、IFSの最初のバイトも特別"${named_array[*]}"です
しかし

さらにいくつかのポイント:1ワードの分割は、$IFSリストコンテキスト(演算子のsplit一部)で引用符で囲まれていない変数を展開するときに実行される2つの主なものの1つですsplit+glob。もう1つはグロビングです。作業分割を使用する場合、通常set -fglobパーツを無効にするために発行する必要があります。
ステファンシャゼル

3
3-は$IFSまたによって使用されるread組み込みコマンド
ステファンChazelasを

22

ドル記号で囲まれた単一引用符内では、一部の文字が特別に評価されます。たとえば、\nは新しい行に変換されます。

したがって、この特定の行は、変数IFSに改行を割り当てます。IFSは、bashの特別な変数である:内部フィールドセパレーターです。man bashそれを言います

展開後の単語分割と、read組み込みコマンドで行を単語に分割するために使用されます。デフォルト値は<space><tab><newline>です。


5
+1 dollared single quotesは、単純な単一引用符とは異なります。
スノークラッシュ

2
@Snowcrash +1 は、単純な単一引用とは異なるドル記号付き単一引用符について言及する場合に+1と言います。申し訳ありませんが、それを助けることができませんでした:)しかし、実際には重要であるため、指摘するのは本当に良いことです!
プリフタン

1
@Pryftan +1 for +1 for +1 ...ご存じのように...それは本当に重要です。
0xc0de

@ 0xc0de間違いなく同意!それをありがとう!:)
プリフタン

15

簡単に言えば、変数IFS=$'\n'に改行\nを割り当てますIFS

$'string'コンストラクトは、エスケープシーケンスのようなANSI Cのデコードに使用する引用メカニズムです。この構文はから来ているksh93、など現代の殻に移植しましたbashzshpdkshbusybox sh

この構文はPOSIXでは定義されていませんが、SUS issue 7で受け入れられました。


-1

$IFS例で説明し
たいと思います:cpまたはmvまたは別のファイル処理を行うSuppsoe、IFSはデフォルトで空です、ファイルにメタ文字またはスペースがある場合:
Linux Administration.pdfまたはFree Software Fundation.ogg、 seperate paramおよびAdministartionは、separate param.Soを考慮しbuilt-in variableます。bashにはがありますIFS==$(echo -en "\n\b")。その後、に初期化でき、bashはファイル名の間のメタ文字とスペースを破棄します。次に例を示します。

#!/bin/bash
SAVEIFS=$IFS
IFS=$(echo -en "\n\b")
mymusicdir=~/test/dd
find $mymusicdir -name "*" -execdir rename 's/ /_/g' "{}" +
IFS=$SAVEIFS
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.