P.P
P.P

Reputation: 121407

Single quote expansion within an array

AFAICT, anything inside a single quotes shouldn't be expanded. Bash manual says:

Enclosing characters in single quotes preserves the literal value of each character within the quotes. A single quote may not occur between single quotes, even when preceded by a backslash.

However, in an older bash version this doesn't appear to be true in Bash 3.00.15(1)-release.

For example, consider (this is a contrived example of a bigger script):

#!/bin/bash

func() {
local -a cmds=('echo subshell echo hi')

    for cmd in "${cmds[@]}"; do
        echo "cmd: $cmd"
    done
}

func

prints:

cmd: echo
cmd: subshell
cmd: echo
cmd: hi

whereas I expected:

cmd: echo subshell echo hi

This is not an issue in newer bash versions. The above works as expected in Bash 3.2.25(1)-release and 4.3.46(1)-release.

Is this a bug in older bash shells? How can work around it so that single quoting preserves values (as I expected above) in bash 3.00.15(1)-release?

Upvotes: 3

Views: 128

Answers (1)

chepner
chepner

Reputation: 531708

At least in bash 3.00.16 (the closest I could compile without manually patching 3.00), the bug appears to be related including the assignment in the local command. The following produces the expected output:

func() {
    local -a cmds
    cmds=('echo subshell echo hi')

    for cmd in "${cmds[@]}"; do
        echo "cmd: $cmd"
    done
}

func

This isn't specific to local; it appears to be a problem with processing assignments that appear as arguments.

bash-3.00$ declare -a foo=('echo bar')
bash-3.00$ printf '%s\n' "${foo[@]}"
echo
bar
bash-3.00$ foo=('echo bar')
bash-3.00$ printf '%s\n' "${foo[@]}"
echo bar

Upvotes: 4

Related Questions