不能将$ @的所有参数与sh -c

时间:2019-04-08 18:23:57

标签: bash command-line-arguments

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

$@

编辑1:如果我将$ 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 数组复制到一个变量中,它将起作用:

$@

如何在$ args=("$@") $ sh -c "echo ${args[*]}" --no-resume-playback https://www.facebook.com/TBN/videos/1580372468665943/ 调用中使用$@的所有参数?

2 个答案:

答案 0 :(得分:7)

$@会扩展为单独的单词,即使使用双引号并且看起来像一个单词也是如此。您编写的命令将扩展为:

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

命令运行为echo --no-resume-playback,其中$0设置为Facebook URL。 echo --no-resume-playback不使用$0,因此有效地将其丢弃。

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

sh -c "echo $*"

这有点危险,因为带有通配符(例如*)的任何参数都可以扩展。为了安全起见,您需要以下更复杂的版本:

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

这会将"$@"作为-c命令的参数转发,以便我们可以依次在其中使用"$@"。请注意,我现在切换到单引号:我们希望子外壳展开"$@",而不是外壳。

实际上,对于最大的步伐echo也不是完全安全的。如果您尝试打印类似-n的字符串,则可能无法按原样打印,而是将其解释为一个选项。最安全的选择是使用printf

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

答案 1 :(得分:1)

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

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

符合您的需求吗?