codeforester's helpful answer explains the issue well.
As for a solution:
Note: If the input you're dealing with doesn't actually have embedded quoting to demarcate elements, simply use readarray -t array < <(...)
as is, where (...
) represents the output-producing command whose lines should be captured as the individual elements of an array.
xargs
generally understands shell quoting in literal input (except for escaped, embedded quotes):
words="'hello world' how are you"
echo "$words" | xargs -n 1 printf '%s\n'
hello world
how
are
you
Note how hello world
was recognized as a single argument, and how its enclosing '
instances were removed.
To utilize this when creating an array in bash
(assumes Bash 4.x due to readarray
, but it's possible to make it work in Bash 3.x[1]
):
words="'hello world' how are you"
readarray -t array < <(xargs -n 1 printf '%s\n' <<<"$words")
declare -p array
which yields:
declare -a array=([0]="hello world" [1]="how" [2]="are" [3]="you")
(The enclosing "
instances are an artifact of the declare -p
output format - they have syntactic function, if you were to reuse the output as shell source code.)
[1] A Bash v3+ solution, using read
instead of readarray
:
words="'hello world' how are you"
IFS=$'\n' read -d '' -ra array < <(xargs -n 1 printf '%s\n' <<<"$words")
declare -p array