在bash中进行基本数值计算

在bash中进行基本数值计算

由于bash是一种解释性语言,所以在bash中,默认情况下,只会进行字符串的运算,比如:

bash 复制代码
x=3+2
echo ${x}

上述代码的结果不是5,而是字符串3+2。这是bash的特性,要进行数值运算,必须使用shell扩展或者内置命令。

如何在bash中计算数值运算

bash中,提供了3种方法来计算数值运算,分别是:

  • 使用(())复合命令
  • 使用let内置命令
  • 使用declare内置命令

使用复合命令进行数值计算

使用(())复合命令进行数值计算,在bash使用中是使用最多的,最普遍的,只需要将要计算的式子放入到(())复合命令中即可,比如上述的代码可以修改为如下:

bash 复制代码
x=$((3+2))
echo ${x}

在进行复合命令的时候,没有语法要求,直接将表达式写入复合命令中即可,不需要刻意在计算符号留空格。

上述代码的输出结果就是5,不过要注意的是,复合命令需要搭配$符号来使用,式子中可以直接引用变量,而无需进行变量替换,比如:

bash 复制代码
x=2
y=3

z=$((x+y))
echo ${z}

a=$((${x}+${y}))
echo ${a}

在上述代码中,虽然za的最后的值都是5,但是这2个式子其实是有区别的,z计算的是xy变量的值,而a计算的是xy引用数值值,实际上是在计算23的值。

使用内置命令let进行数值计算

除了使用(())内置命令计算数值以外,还允许使用内置命令let来进行数值运算,使用过程也非常简单,只需要在计算变量之前使用let关键字即可,比如同样计算上述的2+3,案例如下:

bash 复制代码
x=2
y=3

let z=x+y
echo ${z}

此时z的值当然是5,使用let进行计算的时候,需要注意,数字和表达式之间不能有空格,比如:

bash 复制代码
let z=x + y

这个是有问题的,当bash在执行到空格的时候会报错,此时会将将错误抛出来,而将x的值返回给z

比如案例如下:

bash 复制代码
x=2
y=3

let z=x + y
echo ${z}

执行结果为

bash 复制代码
# bash a.sh
a.sh: line 6: let: +: arithmetic syntax error: operand expected (error token is "+")
2
#

上述所述,z的值将会为2,而报错将会通过stderr输出输出,不会影响程序后续执行。

但是在bash中,使用let计算的时候,如有空格,可以使用括号括起来,比如:

bash 复制代码
let z='x + y'

此时,z的结果将会为5,空格不能影响其结果。

使用内置命令declare进行数值计算

使用declare中的-i参数,可以将变量给声明为int类型,而后进行数值运算的时候,解释器会进行数值运算,而非进行字符串运算,比如同样的3+2,使用declare,可以将其写为:

bash 复制代码
x=2
y=3

declare -i z
z='x + y'
echo ${z}

上述例子中,将z给声明为了int类型的变量,而在进行x+y的时候,会进行数值运算,从而得到结果为5,这里需要注意,如果表达式有空格,必须使用引号将式子括起来。

如果不括起来的话,则会报错,且待计算变量的值为初值,比如:

bash 复制代码
  declare -i z
  z=x + y

假设已经提前定义好了xy的值,当计算z=x + y的时候,由于表达式有空格,所以会报错,且z的值为初值,即空值,这是和let计算不一样的地方。

bash运算操作符

普通运算符

bash中,提供了如下运算法:

  • 加法、减法:+-
  • 乘法、除法:*/
  • 取余:%
  • 幂运算:**

这些都比较基础,可以通过下面案例说明:

bash 复制代码
declare -i x=0

x=x+7
echo x+1: ${x}

x=x-2
echo x-2: ${x}

x=x/3
echo x/3: ${x}

x=x*5
echo x*5: ${x}

x=x%3
echo x%3: ${x}

x=x**3
echo x**x: ${x}

上述例子中,首先声明了x为整形,而后分别计算:

x+7x-2x/3x*5x%3x**3这些表达式的结果,其中第一个表达式的结果,将作为第二个表达式x变量的值来使用,其次类推。

最后运行的值为:

bash 复制代码
# bash a.sh
x+1: 7
x-2: 5
x/3: 1
x*5: 5
x%3: 2
x**x: 8
#

通过简单的运算,可以发现上面的结果都符合预期。

比较运算

bash中还支持比较运算,其运算符为:

  • <:小于
  • >:大于
  • <=:小于等于
  • >=:大于等于
  • ==:判断相等
  • !=:判断不等

首先,在bash中,是没有bool类型的,而是利用返回值进行判断,当为true的时候,返回0,当为false的时候,将会返回非0数字。

在传统shell中,判断相等使用test表达式,搭配-eq来使用,而使用$?来获取命令的返回值,比如:

bash 复制代码
# test 3 -eq 2
# echo $?
1
#

上面例子判断3是否和2相等,再获取其返回值,返回值为1可以理解为返回false

bash 复制代码
# test 3 -eq 3
# echo $?
0
#

而当判断3是否和3相等的时候,返回的是0,则可以理解为true

bash中,注意,这个是bash的特性,可以直接使用熟知的比较运算符了,比如><等等,不过需要搭配bash特定的(())语法使用。

基于如上所述,可以搭配(())语法,可以写一些比较完整的例子。

大于、小于、大于等于、小于等于案例脚本:

bash 复制代码
#!/bin/bash

declare -i x=$1
declare -i y=$2

echo x:${x} y:${y}

# 大于和小于
if ((x > y));then
        echo 'x > y'
else
        echo 'x < y'
fi

# 大于等于 和 小于等于
if (( x>=y ));then
        echo 'x >= y'
fi

if (( x<=y ));then
        echo 'x <= y'
fi

# 相等和不相等
if (( x==y ));then
        echo 'x == y'
fi

if (( x!=y ));then
        echo 'x != y'
fi

上述脚本,从命令行去第一个参数赋值给x、取第一个参数赋值给y,然后进行xy的大小判断,若x大于y,则输出x > y,反正则输出x < y。大于和小于也是一样的。

分别测试3组数据,结果如下:

bash 复制代码
# bash a.sh 1 3
x:1 y:3
x < y
x <= y
x != y
# bash a.sh 3 1
x:3 y:1
x > y
x >= y
x != y
# bash a.sh 1 1
x:1 y:1
x < y
x >= y
x <= y
x == y
#

上述测试了3组例子,结合传入的参数来看,是能够达到预期的。

自增、自减

bash中,可以使用x++x--++x--x相关运算符的,但是它只会计算结果,不会将值叠加到自身变量中,还是需要赋值的形式才行。

比如有如下代码:

bash 复制代码
declare -i x
++x

这种语法是错误的,++x并不会自行迭代增加,而是一个表达式,需要写入到一个变量中,比如:

bash 复制代码
declare -i x
x=++x

这样才会一个完整的表达式,其该x的值将会是1

前自增 和 后自增的区别,可以写一个案例说明,如有以下代码:

bash 复制代码
#!/bin/bash

declare -i x=1
declare -i y
y=x++

echo x: ${x}
echo y: ${y}

如上代码表示后自增,该代码的含义为,现将x的值赋值给y,然后实现自身变量+1,所以上述结果应该是y1,而x2

bash 复制代码
# bash a.sh
x: 2
y: 1
#

如果是前自增,则会先使变量的值+1,然后再赋值给其他变量,比如,有如下代码:

bash 复制代码
#!/bin/bash

declare -i x=1
declare -i y
y=++x

echo x: ${x}
echo y: ${y}

如上代码,xy的结果,都应该为2,因为x首先进行自增1,然后再赋值给y

前自减,后自减也是类似的原理,比如有如下代码片段:

bash 复制代码
declare -i x=2
declare -i y

y=--x

最后的结果是xy的值,都将为1,这是因为在进行--x运算中,先进行x-1,赋值给x,然后再赋值给y,所以说,y的结果也是1

而对于后自减,则先进行赋值,而后在减1,比如有如下代码片段:

bash 复制代码
declare -i x=2
declare -i y

y=x--

上述代码,y的值为2,而x的值为1

总结

bash中,有3种方式可以进行数值运算,分别是使用(())复合命令,使用内置命令let,以及将变量声明为整形的declare -i命令,其中除了(())在计算中,允许变量之间出现空格,其余2种都不能有空格,否则会计算失败,不同的是let计算失败会取用中间值,而declare -i定义的变量计算失败,则会为初值。

bash中进行数值运算的时候,需要将其转换为整形才行,否则默认会进行字符串匹配运算,而在进行比较运算的时候,可以使用bash特性,将表达式包含在(())进行计算。

此前写过关于sh对于数值的判断,相对于bash而言,在bash中进行数值判断,有一丢丢高级语言的味道了。

相关推荐
粉红色回忆2 天前
linux 如何自定义文件描述符
shell
薛定谔的猫_C8T62 天前
程序人生-Hello’s P2P
c语言·汇编·程序人生·shell·二进制·计算机系统·hello
孙克旭_3 天前
day027-Shell自动化编程-基础
linux·运维·自动化·shell
shut up3 天前
Git的使用技巧
gitee·github·shell
粉红色回忆3 天前
linux简单理解输入输出重定向
shell
开挖掘机上班4 天前
Bash shell四则运算
linux·开发语言·bash·shell
Johny_Zhao4 天前
Linux服务器(CentOS/Ubuntu)接口Bond模式详解、配置指南及交换机对应接口的配置示例
linux·网络安全·信息安全·云计算·shell·cisco·huawei·系统运维·华三
粉红色回忆4 天前
简单理解linux文件描述符
shell
Johny_Zhao5 天前
Burp Suite 企业级深度实战教程
linux·网络·网络安全·信息安全·云计算·shell·burp suite·系统运维·itsm