在旧版本中,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
分成一个空元素。
或使用具有适当拆分运算符的shell:
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