Bash: Append to array using while-loop

From FVue
Jump to: navigation, search

Problem

How can I append values to an array from within a while-loop? Of course, the values may contain special characters.

Solution

Change IFS (Field Seperator) to a newline.

foo() {
    local IFS=$'\t\n'              # Set IFS to Tab & Newline (no space)
    a=( "b c" )                    # Array to append to, containing one element "b c"
                                   # Three values to append, separated by newline
    append="d e
f\"g
\$PWD"
    # NOTE: The dash (-) prevents error "unbound variable" when `-u' or
    #       `-o nounset' is set and `a' is empty array.
    a=( ${a[@]-} $(
        echo "$append" | {
            while read i; do
                echo $i
            done
        }
    ))
} # foo()

Running the code above, shows array `a' contains four elements:

$ foo
$ declare -p a
declare -a a='([0]="b c" [1]="d e" [2]="f\"g" [3]="\$PWD")'

Caveat: commented quote in subshell causes error up to and including bash-3.1

Do not use quotes (single or double) within comments within a subshell, because there's a bug in bash (<= 3.1):

$ echo $(#'
> )
bash: bad substitution: no closing `)' in $(#'
)
$

This bug has been fixed in bash-3.2.

See also: Commented quotes in subshells cause syntax errors - Bug-bash mailing list

See also

Bash Reference Manual - Arrays
The Array reference. Did you know you can separate array items using IFS='x'; echo "${array[*]}";
Assorted tips
Example for passing and returning arrays to a function

<amazon asin="0596526784" height="240" name="product" width="120"/>

Journal

20071217

Trying `eval':

foo() {
    a=( "b b" "c c" )
    append="d e
f\"g
\$PWD"

    eval a=( "${a[@]}" $(echo "$append" | {
        while read i; do
            echo "$i" | sed -e "s/\"/\\\\\\\\\\\\&/g" \
            -e "s/.*/\"&\"/"
            #| \ sed -e "s/[][(){}<>\",:;^&!$&=?\`|\\ ']/\\\\\\\\\\\\&/g"
        done
    }))

    for i in "${a[@]}"; do echo i: $i; done
}
foo

Comments

blog comments powered by Disqus