Reputation: 1598
I have a variable that looks sort of like this:
msg="newton apple tree"
I want to assign each of these words into separate variables. This is easy to do in bash:
read a b c <<< $msg
Is there a compact, readable way to do this in POSIX shell?
Upvotes: 15
Views: 4722
Reputation: 531808
A here string is just syntactic sugar for a single-line here document:
$ msg="foo * bar"
$ read a b c <<EOF
> $msg
> EOF
$ echo "$a"
foo
$ echo "$b"
*
$ echo "$c"
bar
Upvotes: 34
Reputation: 123560
To write idiomatic scripts, you can't just look at each individual syntax element and try to find a POSIX equivalent. That's like translating text by replacing each individual word with its entry in the dictionary.
The POSIX way of splitting a string known to have three words into three arguments, similar but not identical to read
is:
var="newton apple tree"
set -f
set -- $var
set +f
a=$1 b=$2 c=$3
echo "$a was hit by an $b under a $c"
Upvotes: 11
Reputation: 295639
It's not pretty, but as a general-purpose solution, you can work around this with a named pipe.
From BashFAQ #24:
mkfifo mypipe
printf '%s\n' "$msg" >mypipe &
read -r a b c <mypipe
printf
is more reliable / better-specified than echo
; echo behavior varies between implementations if you have a message containing only, say, -E
or -n
.
That said, for what you're doing here, you could just use parameter expansion:
a=${msg%% *}; msg=${msg#* }
b=${msg%% *}; msg=${msg#* }
c=${msg%% *}; msg=${msg#* }
Upvotes: 7