不能将 $@ 的所有参数与 sh -c 一起使用

Cannot use all arguments of $@ with sh -c

在脚本中,我有一个涉及 $@sh -c 命令,但似乎只考虑了 $@ 的第一项:

$ set -- --no-resume-playback https://www.facebook.com/TBN/videos/1580372468665943/
$ echo "$@"
--no-resume-playback https://www.facebook.com/TBN/videos/1580372468665943/
$ sh -c "echo $@"
--no-resume-playback
$ sh -c "echo ${@[*]}"
bash: echo ${@[*]}: bad substitution

编辑 1:如果我将 $@ 数组复制到一个变量中,它会起作用:

$ args=("$@")
$ sh -c "echo ${args[*]}"
--no-resume-playback https://www.facebook.com/TBN/videos/1580372468665943/

如何在 sh -c 调用中使用 $@ 的所有参数?

$@ 扩展为单独的词,即使它在双引号中并且看起来像一个词。您编写的命令扩展为:

sh -c "echo --no-resume-playback" https://www.facebook.com/TBN/videos/1580372468665943/

命令 运行 是 echo --no-resume-playback[=16=] 设置为 Facebook URL。 echo --no-resume-playback 没有使用 [=16=],所以它实际上被丢弃了。

你对 ${@[*]} 的想法是正确的。碰巧的是,$@ 是一种具有独特语法的特例:您需要 $*,它扩展为一个单词。

sh -c "echo $*"

这有点危险,因为任何带有像 * 这样的通配符的参数都可能被扩展。如果你想安全起见,你需要这个更复杂的版本:

sh -c 'echo "$@"' sh "$@"

这会将 "$@" 作为参数转发给 -c 命令,这样我们就可以在里面使用 "$@"。请注意,我现在已切换到单引号:我们希望 subshell 扩展 "$@",而不是外部 shell.

实际上,对于最大程度的迂腐,echo 也不是完全安全的。如果你尝试打印一个像 -n 这样的字符串,它可能不会按字面打印,而是被解释为一个选项。最安全的选择是使用 printf:

sh -c 'printf "%s\n" "$*"' sh "$@"

您是否尝试过使用 $* 扩展? 我得到以下信息:

$ sh -c "echo $*"
--no-resume-playback https://www.facebook.com/TBN/videos/1580372468665943/

符合您的需求吗?