IFS = $ '\ n'の正確な意味は何ですか?


123

IFS環境変数を改行文字に設定する次の例の場合...

IFS=$'\n'
  • 何をしないドル記号は意味 を正確に
  • この特定のケースでは何をしますか?
  • この特定の使用法の詳細はどこで確認できますか(Googleは検索で特殊文字を許可しておらず、他に何を探すべきかわかりません)?

IFS環境変数と\n文字(ラインフィード)は知っていますが、次の形式を使用しないのはなぜ IFS="\n"ですか(これは機能しません)?

たとえば、ファイルのすべての行をループしてforループを使用したい場合は、次のようにします。

for line in (< /path/to/file); do
    echo "Line: $line"
done

ただし、がIFS改行文字に設定されていない限り、これは正しく機能しません。これを機能させるには、次のようにする必要があります。

OLDIFS=$IFS
IFS=$'\n'
for line in (< /path/to/file); do
    echo "Line: $line"
done
IFS=$OLDIFS

注:同じことをするのに別の方法は必要ありません。他にもたくさん知っています...私はそれについて知りたいだけで$'\n'、誰かが私にそれについて説明してくれるかどうか疑問に思っています。

回答:


161

通常bash、文字列リテラルのエスケープシーケンスは解釈しません。つまり、\norまたは"\n"or を書いた場合'\n'、それは改行ではありません-文字n(最初の場合)またはバックスラッシュとそれに続く文字n(他の2つの場合)です。

$'somestring'は、エスケープシーケンスを含む文字列リテラルの構文です。とは異なり'\n'$'\n'実際には改行です。


2
厳密にはそうで\nはありません- 単なる(エスケープされた)文字nです。あなたはその通りで'\n'あり"\n"、バックラッシュとそれに続くnです。
Roman Cheplyaka

15
これ$'\n'はbash固有であることに注意してください-POSIXシェル(/bin/sh)では機能しません。POSIX準拠の方法で同じ効果を得るには、と入力しIFS='、次にReturn キーを押して実際の改行文字を入力してから、終了を入力します'
Richard Hansen

23
IFS=$(echo -e '\n')また、POSIX互換の方法で行う必要があります。
Vineet

12
@Vineet-それは私が投票されたコメントに異議を唱えるために一時停止を与えました。これ Posix正解ですが、機能しません。bashのコマンド置換演算子は、末尾の改行文字をすべて削除します。詳細はこちらをご覧ください。
Digital Trauma 2013年

9
:@DigitalTrauma私はそれもPOSIXではないと思う-e定義されていない、と\nすることなく、-eXSI拡張として作品:pubs.opengroup.org/onlinepubs/9699919799/utilities/...printf '\n'rocks;)
Ciro Santilli郝海东冠状病六四事件法轮功

20

構成に正式な名前を付けるだけです。形式の文字列はANSI C引用文字列$'...'と呼ばれます

つまり、[ANSI] C文字列と同様に、バックラッシュエスケープシーケンスが認識され、対応するリテラルに展開されます(サポートされるエスケープシーケンスの完全なリストについては、以下を参照してください)。

この展開$'...'文字列は文字列と同じように動作し'...'ます。つまり、文字列リテラルとして扱われ、[さらに]シェル展開の対象にはなりません

たとえば$'\n'、リテラルの改行文字に展開されます。これは、通常のbash文字列リテラル('...'または"...")で実行できないものです。[1]

もう一つの興味深い特徴は、ということであるANSI C-引用符で囲まれた文字列をエスケープすることができます'ように(単一引用符)\'これは、'...'(通常の単一引用符で囲まれた文字列は)できませんが。

echo $'Honey, I\'m home' # OK; this cannot be done with '...'

サポートされているエスケープシーケンスのリスト

バックスラッシュエスケープシーケンスが存在する場合は、次のようにデコードされます。

\警告(ベル)

\ bバックスペース

\ e \ Eエスケープ文字(ANSI Cではない)

\ fフォームフィード

\ n改行

\ rキャリッジリターン

\ t水平タブ

\ v垂直タブ

\バックスラッシュ

\ '単一引用符

\ "二重引用符

\ nnn 8進値nnn(1から3桁)である8ビット文字

\ xHH値が16進値HH(1桁または2桁の16進数)である8ビット文字

\ uHHHH値が16進値HHHH(1から4桁の16進数)であるUnicode(ISO / IEC 10646)文字

\ UHHHHHHHH値が16進値HHHHHHHH(1から8桁の16進数)であるUnicode(ISO / IEC 10646)文字

\ cx control-x文字

展開された結果は、ドル記号が存在しないかのように、単一引用符で囲まれています。


[1]ただし、実際の改行を「...」および「...」文字列に埋め込むことはできます。つまり、複数行にまたがる文字列を定義できます。


16

http://www.linuxtopia.org/online_books/bash_guide_for_beginners/sect_03_03.htmlから:

「$ 'STRING'」の形式の単語は特別な方法で処理されます。単語は文字列に展開され、バックスラッシュでエスケープされた文字はANSI-C標準で指定されたとおりに置き換えられます。バックスラッシュエスケープシーケンスは、Bashのドキュメントに記載されています。

スクリプトがラインフィードを適切なANSI-C標準にエスケープすることを強制していると思います。


8

デフォルトのIFSに戻す-これOLDIFS=$IFSは必要ありません。サブシェルで新しいIFSを実行して、デフォルトのIFSを上書きしないようにします。

ar=(123 321); ( IFS=$'\n'; echo ${ar[*]} )

さらに、私はあなたが古いIFSを完全に回復するとは本当に信じていません。などの改行を避けるために、二重引用符で囲む必要がありますOLDIFS="$IFS"


2
これは本当に便利なテクニックです。私はそれをよりきれいなシェル結合op:に使用しましたargs=$(IFS='&'; echo "$*")。ボーンシェルフレンドリーな方法でに復元IFSすること$' \t\n'は、決して偉業ではありません。
jeberle 2014年

Besides I don't really believe you recover the old IFS fully:単語分割がされていない変数の代入のRHS上で実行(ただし、引用除去がある)、これOLDIFS=$IFSOLDIFS="$IFS"同じように振る舞います。
mklement0 2015年

3

ANSI Cで引用された文字列が重要なポイントです。@ mklement0に感謝します。

ANSI Cで引用された文字列は、コマンドodでテストできます。

echo -n $'\n' | od -c
echo -n '\n' | od -c
echo -n $"\n" | od -c
echo -n "\n" | od -c

出力:

0000000  \n  
0000001

0000000   \   n   
0000002

0000000   \   n   
0000002

0000000   \   n   
0000002

アウトプットで意味がわかります。


-7

変数から値を取得するようなものです。

VAR='test'
echo VAR
echo $VAR

は異なるため、基本的にドル記号はコンテンツを評価します。


6
これは変数とは関係ありません。$'FOO'$FOOこれが問題だったのとは異なり)文字列リテラルです。実行するとecho $'VAR'VARではなく文字列が出力されることがわかりますtest
sepp2k 2010年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.