Nas versões antigas, bashvocê tinha que citar variáveis depois <<<. Isso foi corrigido no 4.4. Nas versões anteriores, a variável seria dividida no IFS e as palavras resultantes unidas no espaço antes de serem armazenadas no arquivo temporário que compõe esse <<<redirecionamento.
No 4.2 e antes, ao redirecionar os componentes internos como readou command, essa divisão levaria o IFS para o componente interno (4.3 corrigiu isso):
$ 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
Essa foi corrigida em 4.3:
$ bash-4.3 -c 'a=a.b.c.d; IFS=. read x <<< $a; echo "$x"'
a.b.c.d
Mas $aainda está sujeito à divisão de palavras por lá:
$ bash-4.3 -c 'a=a.b.c.d; IFS=.; read x <<< $a; echo "$x"'
a b c d
No 4.4:
$ bash-4.4 -c 'a=a.b.c.d; IFS=.; read x <<< $a; echo "$x"'
a.b.c.d
Para portabilidade para versões mais antigas, cite sua variável (ou use de zshonde ela <<<vem em primeiro lugar e que não possui esse problema)
$ bash-any-version -c 'a=a.b.c.d; IFS=.; read x <<< "$a"; echo "$x"'
a.b.c.d
Observe que essa abordagem para dividir uma string funciona apenas para strings que não contêm caracteres de nova linha. Observe também que a..b.c.seria dividida em "a", "", "b", "c"(sem esvaziar último elemento).
Para dividir seqüências arbitrárias, você pode usar o operador split + glob (o que a tornaria padrão e evitaria armazenar o conteúdo de uma variável em um arquivo temporário da mesma <<<forma):
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
ou:
array=($var'') # in shells with array support
O ''objetivo é preservar um elemento vazio à direita, se houver. Isso também dividiria um vazio $varem um elemento vazio.
Ou use um shell com um operador de divisão adequado:
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