I'm having trouble forming a bash array from a standard output. I've boiled it down to this minimal example:
~$ a=($(echo '1 2 3 "foo bar"'))
~$ echo ${a[0]}
1
~$ echo ${a[1]}
2
~$ echo ${a[2]}
3
~$ echo ${a[3]}
"foo
~$ echo ${a[4]}
bar"
I believe what is happening is that "foo
and bar"
are considered separate items in the standard output, but the goal would be to consolidate those items into one for the array.
Obviously, I could write a small loop to consolidate these terms into one, but I'm wondering of there is a more elegant solution?
EDIT: What goes in place of echo '1 2 3 "foo bar"'
in my code is fairly convoluted, but the point is that I need to form an array from some unknown standard output of this form.
xargs
recognizes quotes so
mapfile -t a <<<"$(echo '1 2 3 "foo bar"' | xargs -n 1)"
printf "%s\n" "${a[@]}"
1
2
3
foo bar
The process substitution is not only unnecessary, it is directly harmful. You want
a=(1 2 3 "foo bar")
If you know how many items to expect, you can do
read a b c d <<<$(echo '1 2 3 "foo bar"')
Eventually, I guess you can't escape eval
.
You could replace the
some unknown standard output of this form
into lines and read the lines into array by the mapfile
command.
For example, this can be done by perl and it's core module like:
some_command() { echo '1 2 3 "foo bar"'; }
echo "output from some_command"
some_command
echo
echo "Parsed into array"
mapfile -t array < <(some_command | perl -MText::ParseWords -lnE 'say for shellwords($_)')
printf '=%s=\n' "${array[@]}"
what prints
output from some_command
1 2 3 "foo bar"
Parsed into array
=1=
=2=
=3=
=foo bar=
EDIT: Just recognised 1_CR's answer.
mapfile -t array < <(some_command | xargs -n 1)
is much better ;)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With