Попытка разбить строку на две переменные

Я пытаюсь разбить строку на две переменные (без использования цикла while):

var="hello:world"
IFS=':' read var1 var2 <<< $var

echo "var1: $var1"
echo "var2: $var2"

но я не получаю желаемого результата:

var1: 'hello world'
var2: ''

Может кто-нибудь объяснить, возможно ли это сделать (или аналогичным образом)?

Ответ 1

Это ошибка в Bash 4.2. См. ответ chepner для правильного объяснения.


Это о котировках. Использование:

IFS=':' read var1 var2 <<< "$var"
                           ^    ^

вместо

IFS=':' read var1 var2 <<< $var

См. результат:

$ IFS=':' read var1 var2 <<< "$var"
$ echo "var1=$var1, var2=$var2"
var1=hello, var2=world

Но

$ IFS=':' read var1 var2 <<< $var
$ echo "var1=$var1, var2=$var2"
var1=hello world, var2=

Ответ 2

FYI для будущих читателей:

После обсуждения этого вопроса с разработчиками, похоже, это действительно ошибка в bash 4.2 и исправлена ​​в предстоящей версии 4.3. Из журнала изменений ветвей разработки

рррр. Исправлено несколько проблем с IFS, когда оно появилось во временной среде       и используется в перенаправлении.

Несмотря на то, что всегда полезно указывать расширения параметров, код OP должен работать так, как предполагалось, без кавычек.


Вот объяснение ошибки. С кодом

var="hello:world"
IFS=':' read var1 var2 <<< $var

неуказанное $var должно быть одним словом, так как оно не содержит символа в глобальном значении IFS (то есть без пробела). read должен видеть строку hello:world. Поскольку он получил два аргумента, он должен применять разбиение по словам, используя его локальное значение IFS, создавая hello и world, которые назначаются соответственно var1 и var2.

Ошибка заключается в том, что строка здесь, как представляется, подвергается частичному расщеплению с использованием "пропущенного" значения IFS, передаваемого в read. В результате строка становится hello world, но все еще рассматривается как read как одно слово. Поскольку это слово не содержит :, read не разбивает его на два слова, а вся строка присваивается var1.

В bash 4.3, как задокументировано, расширение $var не претерпевает расщепления слов в качестве аргумента оператору <<<; код

var="hello:1:2 world"
IFS=: read var1 var2 <<< $var

устанавливает var1 в hello и var2 в 1:2 world.