alexoneill
alexoneill

Reputation: 538

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.

Upvotes: 5

Views: 249

Answers (3)

clt60
clt60

Reputation: 63974

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

Upvotes: 1

iruvar
iruvar

Reputation: 23394

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

Upvotes: 7

tripleee
tripleee

Reputation: 189936

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.

Upvotes: 4

Related Questions