Linux

為什麼 bash read 不會刪除多餘的尾隨 IFS 字元

  • January 20, 2020

這個命令:

read -d 'z' a < <(printf 'a\n\n\n'); printf "$a"

輸出:

a

bashread刪除了預期的多餘尾隨換行符。

並通過更改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字元)。

為什麼?

欄位拆分特別忽略了前導和尾隨 IFS 空格。來自GNU Bash 手冊,3.5.7 Word Splitting

如果IFS未設置,或者它的值恰好<space><tab><newline>是預設值,則忽略前面擴展結果的開頭和結尾處的 、 和 序列,並且任何不在開頭或結尾的字元序列都<space>用於<tab>分隔單詞。如果具有非預設值,則在單詞的開頭和結尾處忽略空格字元、和的序列,只要空格字元在 IFS 的值中(一個 IFS 空格字元)。<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|
||

引用自:https://unix.stackexchange.com/questions/562952