Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Creating an Array in Bash with Quoted Entries from Command Output

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.

like image 331
alexoneill Avatar asked Mar 06 '15 15:03

alexoneill


3 Answers

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
like image 128
iruvar Avatar answered Oct 10 '22 07:10

iruvar


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.

like image 33
tripleee Avatar answered Oct 10 '22 06:10

tripleee


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 ;)

like image 1
jm666 Avatar answered Oct 10 '22 07:10

jm666