1

I have encountered a strange behavior when using the read command and unquoted here-string when they still used to be subject to word-splitting (in older versions of bash). Please take a look at the following snippets:

Here echo $line splits on IFS=: and results in echo a b c - OK:

IFS=:
line=a:b:c

echo $line | { read -ra arr; declare -p arr; }

Output:

declare -a arr='([0]="a b c")'

echo $line results in echo a:b:c as it doesn't contain any characters from default IFS and read then splits on IFS=: and correctly populates the array - OK:

unset IFS
line=a:b:c

echo $line | { IFS=: read -ra arr; declare -p arr; }

Output:

declare -a arr='([0]="a" [1]="b" [2]="c")'

Question:

unset IFS
line=a:b:c
echo $line # outputs correctly a:b:c

IFS=: read -ra arr <<< $line
declare -p arr

Output:

a:b:c
declare -a arr='([0]="a b c")'

Here <<< $line should result in <<< a:b:c since $line doesn't contain anything from IFS. read should then correctly populate the array using IFS=: but the result is only one element, space delimited. Why is that?

I am using GNU bash, version 4.1.17(1)-release (sparc-sun-solaris2.11) where here-strings used to be subject to word-splitting. Quoting solves the issue but I don't see how, in this particular case, word-splitting should mess things up since even the echo $line ... example works just fine.

In GNU bash, version 4.4.19(1)-release (x86_64-pc-linux-gnu) (where here-strings are no longer being split) both unquoted and quoted versions work correctly.

mickp
  • 1,679
  • 7
  • 23
  • Sounds like you assume word splitting happens on assignment. It actually happens on expansion. – that other guy Aug 12 '18 at 23:24
  • @thatotherguy nope, I'm aware it happens on expansion :) – mickp Aug 12 '18 at 23:30
  • The [doc](https://www.gnu.org/software/bash/manual/bash.html) says that on here strings: `The word undergoes brace expansion, tilde expansion, parameter and variable expansion, command substitution, arithmetic expansion, and quote removal. Pathname expansion and word splitting are not performed.` So i guess, maybe it was a bug between 4.1 and 4.4 – KamilCuk Aug 12 '18 at 23:33
  • @KamilCukJam yes it was. Word splitting was performed. But it behaves strangely when compared to `echo $line`. – mickp Aug 12 '18 at 23:35
  • There are three snippets of code, to which `echo $line` are you referring? – KamilCuk Aug 12 '18 at 23:37
  • @KamilCuk 2nd vs 3rd. In 2nd the word splitting behaves as expected. It doesn't not in the 3rd, when here string is used. – mickp Aug 12 '18 at 23:41
  • Both `echo $line` are ok. In the 2nd, it gets `echo 'a:b:c' | IFS=: read -ra arr`, so echo is not spliting, spliting is done by `read`. In the third IFS is unset when `echo $line` is done, so line is also not spliting on `:` when echoing. – KamilCuk Aug 12 '18 at 23:48
  • @KamilCukMe yes, I understand that. As I said, I was confused by the behavior of word splitting when used with here-string and `read`. See the accepted answer for explanation. – mickp Aug 12 '18 at 23:50

1 Answers1

1

This is a known bug in bash version 4.2 (and apparently some 4.1.x versions), which was fixed in version 4.3. See this bug-bash thread, which references this StackOverflow question; there is an explanation of the bug in @chepner's answer to that question.

rici
  • 234,347
  • 28
  • 237
  • 341