我一直在尝试比较Bash中的两个数字是否相等(并且如果它们相等则打印一条消息),但是我为这个简单的程序收到一些奇怪的错误消息:
#!/bin/bash
fun2 (){
$x = 3
//#prog.sh: line 4: =: command not found
if [x == 3]
then
//#prog.sh: line 6: [x: command not found
echo "It's 3!"
fi
}
fun2
相应的错误显示在导致这些错误的行下面。
答案 0 :(得分:40)
必须是:
if [ $x -eq 3 ]; then .....
<强>解释强>:
要比较整数,必须使用这些运算符(从man test复制):
INTEGER1 -eq INTEGER2
INTEGER1 is equal to INTEGER2
INTEGER1 -ge INTEGER2
INTEGER1 is greater than or equal to INTEGER2
INTEGER1 -gt INTEGER2
INTEGER1 is greater than INTEGER2
INTEGER1 -le INTEGER2
INTEGER1 is less than or equal to INTEGER2
INTEGER1 -lt INTEGER2
INTEGER1 is less than INTEGER2
INTEGER1 -ne INTEGER2
INTEGER1 is not equal to INTEGER2
运算符==和!=仅用于字符串比较。
获取信息:“[”命令是系统“test”命令的别名。
答案 1 :(得分:3)
对于第一条错误消息,请移除美元符号$
,等号周围不允许有空格=
x=3
对于第二条错误消息,请在$
之前插入空格和美元符号x
,在3
之后插入空格
if [ $x -eq 3 ]
正如@loentar正确指出的那样,它必须是-eq
,而=
和==
都不是。
答案 2 :(得分:3)
Shell脚本并不是真正的完整语言,它在很大程度上依赖于其他外部命令。
变量使用 sigil ,前面是$
。许多shell脚本语言使用变量sigils来帮助区分字符串和变量。
例如:
foo=foo_value
echo foo foo $foo foo
将打印:
foo foo foo_value foo
请注意,字符串的 echo 语句不需要引号。 Windows Batch shell非常相似:
set foo = foo_value
echo foo foo %foo% foo
如您所见,当假设要扩展变量时使用 sigil ,但在定义变量时则不使用 sigil 。那是因为Unix shell是智能shell。他们甚至在执行命令之前就把它命中。 shell将在执行之前替换环境变量:
foo=bar
$foo="whose value is this" #Note the dollar sign!
echo The value of foo is $foo
echo The value of bar is $bar
这将打印出来:
The value of foo is foo
The value of bar is whose value is this
如果您使用set -xv
命令,则会在$foo="whose value is this"
执行之前看到bar=whose value is this"
已扩展为if
。
在像Kornshell和BASH这样的Bourne样式shell中,if
语句不是您认为的那样。 cat "foo" > my_file #Create a one line file with the string foo in it.
if grep -q "foo" my_file #grep command will return a zero exit code if it finds foo
then
echo "The string 'foo' is in file my_file"
fi
命令执行该语句,如果该命令返回零值,将选择 if子句。例如:
test
请注意, if子句不是布尔语句。这是一个执行的实际命令。
在Unix开发早期的某个地方,创建了test
命令。您可以进行 man test 并查看如何使用它。
foo=3
bar=3
if test foo -eq bar
then
echo "foo and bar are equal"
else
echo "foo and bar are not equal"
fi
命令允许您执行此操作:
$ ls -li /bin/test /bin/[
如果你这样做:
[
您将看到名为test
的命令实际存在,并且是if
命令的硬链接。这是为了使foo=3
bar=3
if [ foo -eq bar ]
then
echo "foo and bar are equal"
else
echo "foo and bar are not equal"
fi
语句看起来更像是在常规编程语言中看到的if语句:
[
与上述内容完全相同,但使用test
代替test
。
这解释了为什么在许多测试中需要破折号(它是[
命令的参数,参数以破折号开头!)。它还解释了为什么您需要]
和001
周围的空格。这些是实际的Unix命令,Unix命令必须在它们周围有空格,因此shell可以处理它们。
另一个问题是为什么shell有两组不同的字符串和数字测试。那是因为字符串可能只包含数字,但实际上不是数字。例如,如果您执行广告资源,则可能包含部件号01
和 Shell Script Perl
Boolean Operator Numeric String Numeric String
=================== ======= ====== ======= ======
Equals -eq = == eq
Not Equals -ne != != ne
Greater Than -gt > > gt
Less Than -lt < < lt
Greater or Equals -ge >= >= ge
Less Than or Equals -le <= <= le
。在数字上,它们是相同的,但作为字符串,它们是两个不同的字符串。 shell脚本无法知道。相反,您必须让shell脚本知道它是数字比较还是字符串比较。
Perl有类似的问题,因为你没有将变量声明为数字或非数字:
$ echo "*" #Echos the asterisk
$ echo * #No quotes: Prints all files in current directory
您可以尝试其他一些方法:
*
在执行 echo 命令之前,再次注意shell 扩展 set -xv
。这是shell脚本和典型编程语言之间的主要区别。在实际执行命令之前,shell首先进行扩展(填充环境变量,全局替换,运行子命令)。
set +xv
将显示正在执行的命令,以及shell 在执行之前如何扩展命令。执行{{1}}会关闭它。玩弄它,你很快就会更好地理解外壳。
答案 3 :(得分:2)
空格在[ ]
表达式中是必需的,所以
if [ $x == 3 ]; then
[ ]
测试中需要sigill个变量
答案 4 :(得分:0)
为了清楚起见,使用 ==
表示相等而不是 =
,即使两者都有效。前者鼓励使用 [[
,后者可能与赋值混淆。使用 (( … ))
或 -lt
和 -gt
进行数值比较。
if [[ "${my_var}" == "val" ]]; then
do_something
fi
if (( my_var == 3 )); then
do_something
fi
if [[ "${my_var}" -gt 3 ]]; then
do_something
fi