1
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?

mmh4all
  • 1,612
  • 4
  • 6
  • 21
Marcus Whybrow
  • 19,578
  • 9
  • 70
  • 90

1 Answers1

2

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.
glenn jackman
  • 238,783
  • 38
  • 220
  • 352