2017-01-10 6 views
3

Я бегу Bash версии 4.2.25. Вот мой код:

#!/usr/bin/env bash 

string="one:two:three:four" 

# without quotes 
IFS=: read -ra array_1 <<< $string 
for i in "${array_1[@]}"; do printf "i = [$i]\n"; done 
# output: 
# i = [one two three four] 

# with quotes 
IFS=: read -ra array_2 <<< "$string" 
for i in "${array_2[@]}"; do printf "i = [$i]\n"; done 
# output: 
# i = [one] 
# i = [two] 
# i = [three] 
# i = [four] 

Что объясняет разницу в поведении?

ответ

2

Я не могу воспроизвести вашу проблему в Linux с помощью bash 4.2.46 и bash 4.3.30. Однако, здесь адаптированная версия, которая действительно показывает, описанное поведение:

string="one:two:three:four" 
IFS=: 

read -ra array_1 <<< $string 
for i in "${array_1[@]}"; do printf "i = [$i]\n"; done 
# i = [one two three four] 

read -ra array_2 <<< "$string" 
for i in "${array_2[@]}"; do printf "i = [$i]\n"; done 
# i = [one] 
# i = [two] 
# i = [three] 
# i = [four] 

Это происходит потому, что переменные не фактически разделить на пространствах, они разделены на $IFS (который по умолчанию пробела, табуляции и перевода строки).

Поскольку мы переопределили $IFS, это значения с двоеточиями, мы должны быть осторожны при цитировании. Пространства больше не имеют значения.

Исходный код показывает, что Bash hardcodes a space в string_list, вызванный через write_here_string. Когда IFS не содержит пробела, строка, которая расширяется до нескольких слов, больше не будет read в токенах вдоль аналогичных строк, делая разницу более выраженной.

PS: Это хороший пример того, почему мы всегда должны указывать наши переменные, даже если мы знаем, что они содержат.

1

Похоже на ошибку. Я просмотрел CHANGES и не смог найти ничего конкретного, но в cygwin bash 4.3.48 (8), как цитируемые, так и некотируемые данные дают ожидаемый результат (четыре строки). Когда-нибудь, когда у меня будет полоса пропускания, я буду клонировать repo и обвинять redir.c, чтобы узнать, могу ли я найти некоторые соответствующие коммиты.

+0

Это действительно ошибка, которая частично была рассмотрена в 4.3 и завершена (?) В 4.4. – chepner