このコマンドは次のとおりです。
read -d 'z' a < <(printf 'a\n\n\n'); printf "$a"
出力:
a
bashはread
予想される追加の末尾の改行を削除しました。
そしてnull文字IFS
に変更。
IFS= read -d 'z' a < <(printf 'a\n\n\n'); printf "$a"
次のように出力されます。
a
(blank line)
(blank line)
read
IFS
改行文字が含まれなくなったため、追加の末尾の改行文字は削除されません。
しかし、今同じことをしますが、m
代わりに改行文字を使用すると、次のようになります。
IFS=m read -d 'z' a < <(printf 'ammm'); printf "$a"
出力は次のとおりです。
a
ただし、実際の出力は次のようになります。
ammm
read
つまり、追加の末尾IFS
文字(この場合はm
文字)は削除されません。
なぜ?
答え1
フィールド分割は、特に先行および後続 IFS スペースを無視します。 ~からGNU Bashマニュアル、3.5.7トークン化:
設定されてい
IFS
ない場合、またはその値がデフォルト値の場合<space><tab><newline>
、前の拡張結果の先頭と末尾にある、およびのシーケンスは無視され、<space>
開始<tab>
または終了以外の文字シーケンスは単語を区切るために使用されます。デフォルト以外の値を使用すると、スペース文字はIFS値(IFSスペース文字)にある1つの単語の先頭と末尾にあるスペース文字シーケンス、、、およびを無視します。<newline>
IFS
IFS
space
tab
newline
この例は、空白以外の文字には適用されません。別のフィールド分割インスタンスを使用してこれを確認できます。
bash-5.0$ printf "|%s|\n" $(printf '\n\na\nb\n\n')
|a|
|b|
bash-5.0$ IFS=' '; printf "|%s|\n" $(printf ' a b ')
|a|
|b|
bash-5.0$ IFS=z; printf "|%s|\n" $(printf 'zzazbzz')
||
||
|a|
|b|
||
答え2
デフォルトでは、読み取りでは先行/学習スペースと改行文字が削除されます。 IFSを追加するとデフォルト値があるため、読み取り時にその値は削除されません。
あなたの例では
IFS=m read -d 'z' a < <(printf 'ammm'); printf "$a"
値を提供したので、IFS
2つのフィールド/列がありますが、読み取る変数は1つだけ提供しました。つまり、2番目のフィールドを保持するために別の変数を指定した場合です。
IFS=m read -d 'z' a b < <(printf 'ammm'); printf '%s %s' "$b" "$a"
mmm a
私が詳細を理解していないので、誰がより詳細に説明することができますが、これは私が理解したものです。