3

In bash (works on v4 at least), the following commands allow to assign multiple variables from a string :

IFS=',' read a b <<< "s1,s2"

IFS=',' read a b < <(echo "s1,s2") # an equivalent

After one of these commands :

$ echo $a
s1
$ echo $b
s2

But provided commands are not POSIX-compliant; if run in sh (dash) :

sh: 1: Syntax error: redirection unexpected

What is a POSIX-compliant alternative to those commands? I tried :

IFS=',' echo "s1,s2" | read a b

The command succeeds (return code 0), but echo $a and echo $b then prints nothing.

norbjd
  • 10,166
  • 4
  • 45
  • 80

2 Answers2

4

a and b are set, but due to the pipline, the read command runs in a subshell. When the subshell exits, the variables disappear.

You can read from a here-doc

IFS=, read a b <<END
s1,s2
END

To replace any arbitrary pipeline (or process substitution), you can capture the pipeline's output and put that variable in a heredoc:

output=$( seq 10 20 | paste -sd, )
IFS=, read a b <<END
$output
END
echo "$a"
echo "$b"

outputs

10
11,12,13,14,15,16,17,18,19,20
glenn jackman
  • 238,783
  • 38
  • 220
  • 352
  • Thanks for the clarification, I'm updating the question to explain "`a` and `b` are not set by the command". – norbjd Dec 03 '18 at 15:45
3

In addition to glenn jackman's answer, there is also the option of an explicit named pipe (which is, essentially, what a process substitution replaces):

mkfifo p
echo "s1,s2" > p &
IFS=, read a b < p
chepner
  • 497,756
  • 71
  • 530
  • 681