bashherestring

bash 3 and bash 5 evaluate herestring whitespace differently


I have a script:

#!/bin/bash

{ read a
read b
} <<< $(echo a; echo b)

declare -p a b

I wrote it to f, did chmod +x ./f, and expected that bash ./f and ./f would be identical.

They aren't:

💻~/dev/test[1]$ ./f
declare -- a="a b"
declare -- b=""
💻~/dev/test[2]$ bash ./f
declare -- a="a"
declare -- b="b"

I figured out that bash ./f is using /usr/local/bin/bash which is version 5.0.16, and that ./f using /bin/bash is version 3.2.57.

What changed between those versions to make this evaluate differently? Is this a bug that got resolved?


Solution

  • Before bash 4.4, herestrings were not treated as implicitly quoted. Thus, the result of parameter expansions or command substitutions used to generate a here-string could be string-split (and then re-joined with spaces, no matter which character from IFS was originally used in the splitting).

    This bug was fixed in bash 4.4.

    To work around this bug, always explicitly quote your expansions, even when they're used to populate a heredoc: <<<"$(echo a; echo b)"