如何防止 $@ 与 bash 中的双引号发生冲突?

如何防止 $@ 与 bash 中的双引号发生冲突?

以下示例返回“a b”而不是预期的“ab c”:

test() { bash -c "testargs() { echo \$@; }; testargs $@"; }
test "a b" c

看来这是一个引用问题。如何在不使用“$*”的情况下解决这个问题?

答案1

$@几乎应该只以 形式使用"$@",单独一句话。展开时"stuff$@",会产生一个列表,其中包含stuff前置的第一个位置参数,然后是其他位置参数。例如,如果位置参数是fooand bar,您将得到两个单词:stufffooand bar。这是你的问题之一。

另一个问题是,使用 时sh -c,第一个非选项参数将成为可用的脚本名称$0。后续的非选项参数成为位置参数。所以sh -c 'echo "$@"' foo bar qux打印bar quxfoois in $0, barin$1quxin $2

要将函数的参数传递给脚本,请$@在脚本中使用(而不是像您那样在函数中使用 -"stuff$@"由于双引号而在执行函数的 shell 中展开)。并占$0.

test() { bash -c 'testargs() { echo "$@"; }; testargs "$@"' myscript "$@"; }

答案2

双引号中的 $@ 扩展为多个单词。bash -c接受细绳作为参数,但后面可以跟其他的然后将其分配给以 $0 开头的位置参数。

因此,您可以将参数发送到内部代码,bash -c如下所示:

Test () { bash -c 'echo $@' -- "$@" ; }
Test "a b" c

这也适用于您的情况:

Test () { bash -c 'testargs() { echo $@ ; } ; testargs $@' -- "$@" ; }
Test "a b" c

如果要保留多字参数,请添加双引号:

Test () {
    bash -c 'testargs() {
                 for a in "$@" ; do
                     echo "$a"
                 done
             }
             testargs "$@"' \
        -- "$@"
}
Test "a b" c

我使用了Test,因为test已经存在并且可能会让读者感到困惑。

相关内容