【问题标题】:Cannot use all arguments of $@ with sh -c不能将 $@ 的所有参数与 sh -c 一起使用
【发布时间】:2019-04-09 03:25:59
【问题描述】:

在脚本中,我有一个涉及$@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 调用中使用$@ 的所有参数?

【问题讨论】:

    标签: bash command-line-arguments


    【解决方案1】:

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

    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 "$@"
    

    【讨论】:

    • @JohnKugelman 为什么${@[*]} 不能与@ 变量一起使用?
    • 您可以将$*$@ 视为访问unnamed 命令行参数数组的方法。 ${@[*]} 不起作用,因为数组的名称不是 @。我可能会看到${[@]}${[*]} 的参数,其中省略了名称。
    • sh -c 'echo "$@"' sh "$@" 可以写成sh -c 'echo "$@"' $0 "$@",对吧?
    • 它可以,是的。你可以在那里传递任何东西。有些人通过--。由于您明确调用sh -c,因此传递sh 对我来说是有意义的。
    【解决方案2】:

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

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

    这符合您的需要吗?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-07-29
      • 1970-01-01
      • 1970-01-01
      • 2018-11-29
      • 2013-01-03
      • 2014-04-20
      • 2022-12-04
      • 2017-03-09
      相关资源
      最近更新 更多