input="a b '1 2 3' c"
arr=($input); printf '%s|' "${arr[@]}"
# Prints: a|b|'1|2|3'|c|
eval "arr=($input)"; printf '%s|' "${arr[@]}"
# Prints: a|b|1 2 3|c|
How does one get the latter output without using eval
?
input="a b '1 2 3' c"
arr=($input); printf '%s|' "${arr[@]}"
# Prints: a|b|'1|2|3'|c|
eval "arr=($input)"; printf '%s|' "${arr[@]}"
# Prints: a|b|1 2 3|c|
How does one get the latter output without using eval
?
bash v5.2 ships with dsv
, a CSV parsing loadable command
$ echo "$BASH_VERSION"
5.2.15(1)-release
$ echo "$BASH_LOADABLES_PATH"
/usr/local/lib/bash # your milage may vary here
Then, enable it and parse that string
$ enable dsv
$ input="a b '1 2 3' c"
$ dsv -a arr -d ' ' -S "$input"
$ declare -p arr
declare -a arr=([0]="a" [1]="b" [2]="1 2 3" [3]="c")
To explain the options:
$ help dsv
dsv: dsv [-a ARRAYNAME] [-d DELIMS] [-Sgp] string
Read delimiter-separated fields from STRING.
Parse STRING, a line of delimiter-separated values, into individual
fields, and store them into the indexed array ARRAYNAME starting at
index 0. The parsing understands and skips over double-quoted strings.
If ARRAYNAME is not supplied, "DSV" is the default array name.
If the delimiter is a comma, the default, this parses comma-
separated values as specified in RFC 4180.
The -d option specifies the delimiter. The delimiter is the first
character of the DELIMS argument. Specifying a DELIMS argument that
contains more than one character is not supported and will produce
unexpected results. The -S option enables shell-like quoting: double-
quoted strings can contain backslashes preceding special characters,
and the backslash will be removed; and single-quoted strings are
processed as the shell would process them. The -g option enables a
greedy split: sequences of the delimiter are skipped at the beginning
and end of STRING, and consecutive instances of the delimiter in STRING
do not generate empty fields. If the -p option is supplied, dsv leaves
quote characters as part of the generated field; otherwise they are
removed.
The return value is 0 unless an invalid option is supplied or the ARRAYNAME
argument is invalid or readonly.