如何阻止带有 `IFS` 的 `read` 将空白字符合并在一起?

How do I stop `read` with `IFS` from merging together whitespace characters?

拿这段读入数据的代码来说|

DATA1="Andreas|Sweden|27"
DATA2="JohnDoe||30"   # <---- UNKNOWN COUNTRY
while IFS="|" read -r NAME COUNTRY AGE; do 
    echo "NAME:    $NAME";
    echo "COUNTRY: $COUNTRY";
    echo "AGE:     $AGE";
done<<<"$DATA2"

输出:

NAME: JohnDoe
COUNTRY:
AGE: 30

它应该与这段代码工作,我们正在做完全相同的事情,只是使用 \t 作为分隔符而不是 | ]

DATA1="Andreas  Sweden  27"
DATA2="JohnDoe      30"  # <---- THERE ARE TWO TABS HERE
while IFS=$'\t' read -r NAME COUNTRY AGE; do 
    echo "NAME:    $NAME";
    echo "COUNTRY: $COUNTRY";
    echo "AGE:     $AGE";
done<<<"$DATA2"

但事实并非如此。

输出:

NAME: JohnDoe
COUNTRY: 30
AGE:

Bash 或 readIFS 或代码的某些其他部分在不应该的情况下将空格放在一起。为什么会发生这种情况,我该如何解决?

bash 的行为完全正常。来自 bash 文档:

The shell treats each character of IFS as a delimiter, and splits the results of the other expansions into words on these characters. If IFS is unset, or its value is exactly <space><tab><newline>, the default, then sequences of <space>, <tab>, and <newline> at the beginning and end of the results of the previous expansions are ignored, and any sequence of IFS characters not at the beginning or end serves to delimit words. If IFS has a value other than the default, then sequences of the whitespace characters space and tab are ignored at the beginning and end of the word, as long as the whitespace character is in the value of IFS (an IFS whitespace character). Any character in IFS that is not IFS whitespace, along with any adjacent IFS whitespace characters, delimits a field. A sequence of IFS whitespace characters is also treated as a delimiter.

要克服此“功能”,您可以执行以下操作:

#!/bin/bash

DATA1="Andreas  Sweden  27"
DATA2="JohnDoe          30"  # <---- THERE ARE TWO TABS HERE

echo "$DATA2" | sed 's/\t/;/g' |
while IFS=';' read -r NAME COUNTRY AGE; do
    echo "NAME:    $NAME"
    echo "COUNTRY: $COUNTRY"
    echo "AGE:     $AGE"
done