如何在bash条件表达式中使用变量?

如何在bash条件表达式中使用变量?,bash,shell,Bash,Shell,我想解释一下如何在bash条件表达式中最好地使用变量 我通常这样写if语句: var=1; # some code... if [[ $var -eq 1 ]]; then echo "ok"; else echo "fail"; fi 正如我所预料的,这个返回值ok 现在我在一些脚本中看到了类似的语句,如: var=1; # some code... if [[ var -eq 1 ]]; then echo "ok"; else echo "fail"; fi 唯一的区别是在条件表达式[

我想解释一下如何在bash条件表达式中最好地使用变量

我通常这样写
if
语句:

var=1;
# some code...
if [[ $var -eq 1 ]]; then echo "ok"; else echo "fail"; fi
正如我所预料的,这个返回值
ok

现在我在一些脚本中看到了类似的语句,如:

var=1;
# some code...
if [[ var -eq 1 ]]; then echo "ok"; else echo "fail"; fi
唯一的区别是在条件表达式
[…]
中缺少参数扩展字符
$

实际上,我希望这个语句会给出一个错误,但是这个语法被接受并返回
ok
字符串

我使用
bash
(GNUBash,版本4.3.46)、
zsh
(5.1.1)、
ksh
(93u+2012-08-01)和busybox
ash
(busybox v1.23.2)测试了这条语句

我只收到busybox外壳的一个错误:

ash: var: bad number
我在
bash
手册页的
算术评估
段落中看到:

在表达式中,shell变量也可以通过名称引用,而不使用参数扩展语法

但是我在
条件表达式
一段中没有发现任何与参数扩展相关的特殊内容


那么,在引用变量时,条件表达式是否应该包含
$
?为什么呢?

这里的触发器是
-eq
;因为它被定义为执行整数比较,所以它的操作数是在算术上下文中计算的。不过,这并没有明确的文档记录


不过,您应该使用
$
[[
是一个扩展,因此不能保证它在定义这样一个构造的每个shell中的行为都是相同的。事实上,我甚至不会假设
[[var-eq 3]]
在同一shell的未来版本中将继续以这种方式行为。
((var==3))尽管如此,
被记录为执行
var
的扩展,因为您处于一个明确的算术上下文中。

检查bash手册页中关于
复合命令的部分。特别是以下内容:

((表达式))
表达式根据下面描述的规则进行计算
在算术计算下。如果表达式的值为非零,
返回状态为0;否则返回状态为1。这正是
相当于“let”表达式“`。
[[表达]]
根据条件值的计算返回状态0或1
表达式。表达式由原色组成
下面在条件表达式下描述。
如果您要计算需要算术运算的内容,请使用算术运算,并检查
条件表达式
部分,了解可以使用
[…]]
执行的各种操作。双方括号中的条件可以计算字符串和整数,有时它们的工作方式相同。有时不是

在bash手册页的
条件表达式下

   string1 == string2
   string1 = string2
          True  if the strings are equal.  = should be used with the test command for POSIX conformance.  When used with the [[ command, this performs pattern
          matching as described above (Compound Commands).
...
   arg1 OP arg2
          OP is one of -eq, -ne, -lt, -le, -gt, or -ge.  These arithmetic binary operators return true if arg1 is equal to, not equal to, less than, less than
          or equal to, greater than, or greater than or equal to arg2, respectively.  Arg1 and arg2 may be positive or negative integers.
显然,字符串“1”是字符串“1”,因此如果
n=1
,将
$n
与字符串
“1”进行比较
,你会得到成功。但是你应该知道你在做什么,这不是一个数字比较。同样地,
不是数字比较,它们是字符串比较。所以当
“1”
“2”
,你可能会惊讶于
“11”

也就是说,bash对您要求其评估的情况表示宽容:

bash-4.4$ n=1
bash-4.4$ [[ n -eq 1 ]] && echo yes
yes
bash-4.4$ [[ $n -eq 1 ]] && echo yes
yes
bash-4.4$ (( n == 1 )) && echo yes
yes
bash-4.4$ (( n = 2 )) && echo yes
yes
bash-4.4$ echo "$n"
2
第一种是有效的,因为在此上下文中,
n
只能是一个变量,所以bash将其视为变量。但您不应该依赖于这种行为。在条件表达式中使用美元符号作为变量,并遵循bash的咒语,“始终引用您的变量”

在bash中的双方括号表达式中,如果希望比较是整数,则应使用算术二进制运算符

请注意,您的busybox构建似乎使用的是
ash
,而不是
bash
。ash是“Almquist shell”,一个比bash更老的POSIX shell,编写于20世纪80年代末。ash是FreeBSD中
/bin/sh
的基础,此外在嵌入式系统中通常比bash更受欢迎(因此busybox)因为它体积小


您可能需要考虑编写POSIX shell脚本,而不是BASH shell脚本。这意味着简化一些事情,也可以为其他人跳过一些环。POSIX不包括双方括号表达式,但它确实允许诸如“代码> [“$N”-EQ 1)< /代码>或<代码> [$((n+1))-eq 2 ]之类的东西。。它将在busybox中工作。

如果[[var-eq 1]],则回显“ok”;否则回显“fail”;fi
bash
ksh
@anubhava上为我打印
fail
echo$var
返回什么?:)
declare-p var
显示
-bash:declare:var:not found