使用`if`在变量内运行命令时出错

时间:2017-10-27 03:21:34

标签: shell variables if-statement

我们有一个运行最后两个命令的脚本。但它失败了..

$ if [ -d / ]; then echo a; else echo b; fi
a
$ bash -c 'if [ -d / ]; then echo a; else echo b; fi'
a
$ A="bash -c 'if [ -d / ]; then echo a; else echo b; fi'"
$ $A
[: -c: line 0: unexpected EOF while looking for matching `''
[: -c: line 1: syntax error: unexpected end of file

我真的好奇为什么?谢谢!

2 个答案:

答案 0 :(得分:0)

在上一个命令行中,您已为变量A分配了一个值,但在调用$A之前未能对其进行评估。相反,以下任何一个都可以使用:

定义变量,然后对其进行评估,

 ~]# A="bash -c 'if [ -d / ]; then echo a; else echo b; fi'"
 ~]# eval $A

首先评估它,然后echo评估它。

 ~]# A=$(bash -c 'if [ -d / ]; then echo a; else echo b; fi')
 ~]# echo $A

或者不是个人喜欢的,你也可以使用这个:

 ~]# A="eval bash -c 'if [ -d / ]; then echo a; else echo b; fi'"
 ~]# $A

以上所有内容都会产生a

注意:请参阅为什么不应使用第三个选项:http://mywiki.wooledge.org/BashFAQ/048

答案 1 :(得分:0)

让我们用一个更简单的例子来解释:

$ A="bash -c 'echo hello'"
$ $A
hello': -c: line 0: unexpected EOF while looking for matching `''
hello': -c: line 1: syntax error: unexpected end of file

执行$A时, shell对$A的值执行单词拆分。 它找到了这些词:

  • bash
  • -c
  • 'echo
  • hello'

您可能希望将'echo hello'评估为值echo hello(不使用单引号),但事实并非如此。 它不可能发生。 使用A设置A="..."的值时, 嵌套在'...'中的任何"..."都不会被评估, 所以文字'仍然存在。 递归计算这样的字符串值会很危险。

因此,在单词拆分后,执行的内容看起来更像是这样:

bash -c "'echo" "hello'"

然后bash尝试执行命令'echo,它失败了, 因为它找不到匹配的'

至于错误消息的hello':前缀是什么, 我相信man bash的摘录解释了:

SYNOPSIS
       bash [options] [command_string | file]

...

       -c        If the -c option is present, then commands are read from  the
                 first non-option argument command_string.  If there are argu-
                 ments  after  the  command_string,  the  first  argument   is
                 assigned  to  $0  and any remaining arguments are assigned to
                 the positional parameters.  The assignment  to  $0  sets  the
                 name  of  the  shell, which is used in warning and error mes-
                 sages.

另一个例子,在问题的原始代码中, 错误消息以[:为前缀,因为在"bash -c 'if [ -d / ]; then echo a; else echo b; fi'"的单词拆分之后, 'if之后的下一个字是[

如果你真的想做这样的事情,你可以改用数组:

A=(bash -c 'if [ -d / ]; then echo a; else echo b; fi')
"${A[@]}"

通过这种方式写作,A将有3个值:

  • bash
  • -c
  • if [ -d / ]; then echo a; else echo b; fi

这些将在执行时用作3个单词, 产生预期的输出a