数组内的单引号扩展

3
据我所知,单引号内的任何内容都不应该被扩展。Bash手册如下所述: “将字符用单引号括起来会保留括号内每个字符的字面值。单引号中间不能出现单引号,即使前面加了反斜杠。” 然而,在较旧的bash版本中(例如bash 3.00.15(1)-release),这似乎并不正确。
例如,请考虑以下情况(这是一个更大脚本的人为例子):
#!/bin/bash

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

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

func

打印:

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

然而我预期的是:

cmd: echo subshell echo hi

在更新的bash版本中,这不是一个问题。在Bash 3.2.25(1)-release4.3.46(1)-release中,上述内容按预期工作。
这是旧版bash shell中的一个错误吗?如何解决这个问题,使单引号在bash 3.00.15(1)-release中保留值(如我上面所期望的)?

2
为什么你们要支持这么老的Bash版本?即使是OS X,它多年来都没有更新过Bash,也有3.2.57。 - Barmar
这肯定是个 bug。echo ${#cmds[@]} 显示了什么? - Barmar
3
我不认为SO是一个适合提交十年前的Bug报告的地方。解决方法是逐个分配元素,例如cmds[0]='foo bar'等。另外,升级shell... - hek2mgl
1
@hek2mgl,我认为SO 询问这样问题的完美场所。(而且这个问题提得非常好。)这不是一个bash错误报告,而是一个请求帮助在一种也许不再那么常见的shell方言中编写程序。升级到最新版本并不总是切实可行或可能的,嵌入式系统从ROM复制的软件,轨道上的卫星等等,可能会陷入无法升级的状态。 - ghoti
1
@ghoti我不认为有问题。派些宇航员出去,用新的bash重新刷写ROM,任务完成了。也许他们在那里时还可以清空/var/log。 - hek2mgl
显示剩余6条评论
1个回答

4

至少在 bash 3.00.16 版本中(这是我能够编译而不需要手动打补丁的最接近版本),该 bug 看起来与包含分配在 local 命令中有关。下面的代码将产生预期输出:

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

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

func

这不仅限于local;看起来是处理作为参数出现的赋值语句时的问题。
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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接