0

I'm trying to split a multi-line string on spaces only, preserving line breaks:

IFS=' ' read a b c <<< "$(printf '%s\n' "foo" "bar" "baz")"; echo "a=[$a]"; echo "b=[$b]"; echo "c=[$c]"

Expected:

a=[foo
bar
baz
]
b=[]
c=[]

Actual:

a=[foo]
b=[]
c=[]

What am I missing? When I replace \n with \t it works as expected.

I'm using bash v5.0.18

Cyrus
  • 84,225
  • 14
  • 89
  • 153
Rolf W.
  • 1,379
  • 1
  • 15
  • 25
  • 1
    An assignment on the same line as a command (with no separator such as `;` between them) applies only to that one command (and exports the variable to the environment during that one command's execution, but does not use during other phases shell expansion for that command). – Charles Duffy Oct 25 '20 at 18:15
  • 1
    The other important -- critical -- thing here is that you aren't passing `-d` to your `read`. There are _two_ different separators involved in reading: `IFS` determines the boundary between words within an input field; `-d` determines the boundary between inputs. – Charles Duffy Oct 25 '20 at 18:20
  • 2
    ...make it `IFS=' ' read -r -d '' a b c`, and you'll get your expected behavior. See this demonstrated at https://ideone.com/g2hpuS – Charles Duffy Oct 25 '20 at 18:21
  • Thanks, I wasn't aware of that nuance of the read command. I'm left with one minor issue when I use the `-d ''` flag, which is that it exits with error 1 because there is no newline equivalent at the end of the input: https://ideone.com/l6hL5B (I'm reading into an array now, but the same happens with individual variables). Since the suggested delimiter is an empty string and I guess I can't add that to the end, what safe alternative would you suggest for read to exit successfully? – Rolf W. Oct 27 '20 at 13:39
  • 1
    The usual practice is `read -r -d '' a || [[ $a ]]`, so you have a compound command that returns true if the destination variable was successfully populated. – Charles Duffy Oct 27 '20 at 15:01
  • 1
    BTW, `-d ''` refers to a NUL (C strings being NUL-terminated, the first and only character of an empty string is a NUL). You can emit them with `printf '\0'`. – Charles Duffy Oct 27 '20 at 15:02

0 Answers0