В старых версиях bash
вам приходилось заключать в кавычки переменные после <<<
. Это было исправлено в 4.4. В более старых версиях переменная разделялась на IFS, и результирующие слова объединялись в пространстве перед сохранением во временном файле, который составляет это <<<
перенаправление.
В 4.2 и ранее, при перенаправлении встроенных функций, таких как read
или command
, такое разбиение даже получило бы IFS для этой встроенной функции (4.3 исправило это):
$ bash-4.2 -c 'a=a.b.c.d; IFS=. read x <<< $a; echo "$x"'
a b c d
$ bash-4.2 -c 'a=a.b.c.d; IFS=. cat <<< $a'
a.b.c.d
$ bash-4.2 -c 'a=a.b.c.d; IFS=. command cat <<< $a'
a b c d
Это исправлено в 4.3:
$ bash-4.3 -c 'a=a.b.c.d; IFS=. read x <<< $a; echo "$x"'
a.b.c.d
Но там $a
все еще есть разделение слов:
$ bash-4.3 -c 'a=a.b.c.d; IFS=.; read x <<< $a; echo "$x"'
a b c d
В 4.4:
$ bash-4.4 -c 'a=a.b.c.d; IFS=.; read x <<< $a; echo "$x"'
a.b.c.d
Для переносимости в более старые версии, укажите вашу переменную (или используйте, zsh
откуда она <<<
взялась, и у которой нет этой проблемы)
$ bash-any-version -c 'a=a.b.c.d; IFS=.; read x <<< "$a"; echo "$x"'
a.b.c.d
Обратите внимание, что такой подход для разделения строки работает только для строк, которые не содержат символов новой строки. Также не отметить , что a..b.c.
должно быть разделено на "a"
, ""
, "b"
, "c"
(не пустой последний элемент).
Чтобы разделить произвольные строки, вы можете использовать вместо этого оператор split + glob (который сделает его стандартным и позволит избежать хранения содержимого переменной во временном файле, как это <<<
делается):
var='a.new
line..b.c.'
set -o noglob # disable glob
IFS=.
set -- $var'' # split+glob
for i do
printf 'item: <%s>\n' "$i"
done
или:
array=($var'') # in shells with array support
''
Является сохранение завершающую пустой элемент , если таковые имеются. Это также разделило бы пустое $var
на один пустой элемент.
Или используйте оболочку с правильным оператором разбиения:
zsh
:
array=(${(s:.:)var} # removes empty elements
array=("${(@s:.:)var}") # preserves empty elements
rc
:
array = ``(.){printf %s $var} # removes empty elements
fish
set array (string split . -- $var) # not for multiline $var