传递给另一个bash shell时,Bash会丢弃命令行参数

时间:2016-12-02 16:27:44

标签: linux bash shell

我有一个大脚本(称之为test),在删除不相关的部分之后,归结为使用我可以解释我的问题:

#!/bin/bash

bash -c "$@"

这并不像预期的那样有效。例如。 ./test echo hi只执行echo,参数消失! 使用各种输入进行测试我只能看到$1传递给bash -c ...而其余的被丢弃。

但如果我使用像:

这样的变量
#!/bin/bash

cmd="$@"
bash -c "$cmd"

它可以按预期运行所有输入。

问题:

1)我想理解为什么双引号没有通过" bash -c ...的整个命令行参数。我在这里缺少什么(当使用中间变量时它完全正常)?

2)为什么bash在没有任何错误消息的情况下丢弃其余参数($1除外)

例如:

bash -c "ls" -l -a hi hello blah

只需运行echohi hello blah根本不会导致任何错误?

(如果可能,请参阅记录此行为的bash语法。)

2 个答案:

答案 0 :(得分:1)

您应该使用$*而不是$@来将命令行作为字符串传递。 "$@"扩展为多个带引号的参数,"$*"将多个参数组合成一个参数。

#!/bin/bash

bash -c "$*"

问题在于你执行的$@

bash -c echo hi

但是$*会执行:

bash -c 'echo hi'

使用时:

cmd="$@"

并使用:bash -c "$cmd"它对你做同样的事情。

阅读: What is the difference between “$@” and “$*” in Bash?

答案 1 :(得分:1)

  

1)我想理解为什么双引号不会将整个命令行参数“传递”给bash -c ....我在这里缺少什么(使用中间变量时它完全正常) ?

来自info bash @

  

@        ($@)从1开始扩展到位置参数。当扩展发生在双引号内时,每个参数都会扩展   一个单独的词。也就是说,"$@"相当于"$1" "$2" ...

因此,bash -c "$@"相当于bash -c "$1" "$2" ...。在./test echo hi调用的情况下,表达式扩展为

bash -c "echo" "hi"
  

2)为什么bash在没有任何错误消息的情况下丢弃其余参数($ 1除外)?

Bash实际上并没有丢弃任何东西。来自man bash

  

如果存在-c选项,则从第一个非选项参数command_string读取命令。如果在command_string之后存在参数,则会将它们分配给位置参数,从$0开始。

因此,对于命令bash -c "echo" "hi",Bash将"hi"作为$0传递给"echo"脚本。

  

bash -c "ls" -l -a hi hello blah

     

只需运行echo,你好,你好blah不会导致任何错误吗?

根据上述规则,Bash执行"ls"脚本并将以下位置参数传递给此脚本:

  • $0"-l"
  • $1"-a"
  • $2"hi"
  • $3"hello"
  • $4"blah"

因此,该命令实际执行ls,并且脚本中的位置参数 unused 。您可以通过参考位置参数来使用它们,例如:

$ set -x
$ bash -c "ls \$0 \$1 \$3" -l -a hi hello blah

+ bash -c 'ls $0 $1 $3' -l -a hi hello blah
ls: cannot access hello: No such file or directory