【6.1】Linux bash中的运算

一、使用((表达式)) 或$((表达式)),如果用单小括号,代表包含的是系统命令

root@root:~# a=3
root@root:~# ((b=a+3))
root@root:~# echo $b
6
root@root:~# a=1
root@root:~# b=2
root@root:~# echo $(($a+$b))
3
root@root:~# echo $((3*(6%4)))
6
root@root:~# echo $((1 &&0))
0

二、第二种使用let

root@root:~# let "c=$a+4"
root@root:~# echo $c
7

三、使用expr表达式,注意空格和反引号

root@root:~# d=`expr 4 + 3`
root@root:~# echo $d
7
root@root:~# a=1
root@root:~# b=2
root@root:~# c=$(expr $a + $b) #注意+ 号左右两边必须有空格才有效
root@root:~# echo $c
3

四、放在$[ expression]中,这是bash的推荐的标准处理方法

root@root:~# a=4
root@root:~# b=$[$a-9]
root@root:~# echo $b
-5

五、在C风格的for循环中,则可以如下使用

root@root:~# for((a=1,b=10;a<=10;a++,b--))
do
((c=a*b))
echo "$c"
done
10
18
24
28
30
30
28
24
18
10

六、浮点数运算,借助bc(bash计算器)运算

基本格式: variable=`echo "option;expression" | bc`
root@root:~# a=`echo "scale=4;3.25/3" | bc`
root@root:~# echo $a
1.0833
root@root:~# a=6.6
root@root:~# b=3.5
root@root:~# c=`echo "scale=5;$a/$b"|bc`
root@root:~# echo $c
1.88571

七、如果浮点表达是有多行,则可以放在多行计算

基本格式:

variable=`bc << EOF
options
statements
expressions
EOF
`
演示:
root@root:~# a=1.2
root@root:~# b=2.4
root@root:~# c=3.5
root@root:~# d=2
root@root:~# e=`bc << EOF
scale=4
ab=($a+$b)
cd=($c-$d)
ab+cd
EOF
`
root@root:~# echo $e
5.1

八、Shell中的变量默认都是字符串,可以看到

root@root:~# a=1
root@root:~# b=2
root@root:~# c=$a+$b
root@root:~# echo $c
1+2

九、bash脚本中使用declare 声明变量

基本格式: declare [+/-] [选项] 变量名

选项:     - :给变量设定类型属性

    + :取消变量的类型属性

    -i :将变量声明为整数型(int)

    -x :将变量声明为环境变量

    -p :显示指定变量的被声明的类型

代码:

#!bin/bash
a=1
b=2
c=$a+$b
declare -p a #此步输出 declare -- a="1"
export a
declare -p a #此步输出 declare -x a="1" a已为环境变量
declare -i c=$a+$b
echo $c #输出结果3
root@root:~# bash cmd
declare -- a="1"
declare -x a="1"
3
root@root:~# num=2+3
root@root:~# declare -i num #将num变量数值化
root@root:~# echo $num
2+3
root@root:~# num=9/4
root@root:~# echo $num
2
root@root:~# num=ok #赋值字符串,无法计算,结果为0
root@root:~# echo $num
0

十、基本与或非运算,幂运算,模运算

root@root:~# echo $[ 2>>1 ] #右移
1
root@root:~# echo $[ 2<<1 ] #左移
4
对~8按位取反步骤
转二进制:0 1000
计算补码:0 1000
按位取反:1 0111
转为原码:
按位取反:1 1000
末位加一:1 1001
符号位为1是负数,即-9
root@root:~# echo $[ ~8 ] #按位非
-9

root@root:~# echo $((1^0)) #异或
1
root@root:~# echo $((1^1))
0
root@root:~# echo $((2 & 5)) #按位与
0
root@root:~# echo $((2 && 5)) #逻辑与
1
root@root:~# echo $((2 | 5)) #按位或
7
root@root:~# echo $((2 || 5)) #逻辑或
1
root@root:~# echo $[!2] #非运算
0
root@root:~# echo $[!0]
1
root@root:~# expr 9 \| 3 #两者都不为0,取前者,退出状态码为 0
9
root@root:~# expr 3 \| 9
3
root@root:~# expr 0 \| 0 #都为0,取0,退出状态码为 1
0
root@root:~# expr 0 \| 5 #取不为0的值,退出状态码0
5
root@root:~# expr 5 \| 0
5
root@root:~# expr 9 \& 3 #两者都不为0,取前者,退出状态码为 0
9
root@root:~# expr 3 \& 9
3
root@root:~# expr 0 \& 0 #有一个为0,则结果为0,退出状态码1
0
root@root:~# expr 111 \& 0
0
root@root:~# expr 0 \& 111
0
root@root:~# expr 9 \< 9 #关系为假,结果为0
0
root@root:~# expr 8 \>= 3 * 3
0
root@root:~# expr 8 \> 2 * 3
1
root@root:~# expr -45 / 11 = -4 #一个等号和两个等号都是判断左右是否相等
1
root@root:~# expr 9 != 3 #逻辑结果为1,退出状态码0
1
root@root:~# expr 9 != 7 + 2 #逻辑结果为0,退出状态码1
0
root@root:~# expr 9 = 3 * 3 #逻辑结果为1,退出状态码0
1
root@root:~# echo $((4%6)) #模运算
4
root@root:~# echo $((2**3)) #幂运算
8

十一、随机数,$RANDOM不是一个变量,是一个内置函数

root@root:~# shuf -i 1-10 -n 3
7
5
2
root@root:~# shuf -i 100-1000 -n 3
991
189
487
root@root:~# echo $RANDOM
27727
root@root:~# echo $RANDOM
25622

十二、条件判断

test 等同于 [ ] , -gt 大于,-lt 小于, -eq 等于 , -ne 不等于 , -ge 大于等于, -le 小于等于
root@root:~# test 2 -gt 3
root@root:~# echo $?
1
root@root:~# test 34 -lt 91
root@root:~# echo $?
0
root@root:~# read a b
1 1
root@root:~# if [ $a == $b ]; then echo '俩数相等';fi
俩数相等
root@root:~# read a b
1 2
root@root:~# if [ $a -le $b ] ;then echo 'a 小于等于b';fi
a 小于等于b
root@root:~# read a b
1 '1'
root@root:~# if [ $a = $b ] ;then echo '俩数相等';else echo '俩数不等';fi
俩数不等
判断文件
-d 判断是否是目录,-e判断文件是否存在,-r判断文件是否可读,-w判断文件是否可写,-x判断文件是否可执行
-f判断是否普通文件,-s判断文件大小不为0,-o 或逻辑判断,-a 与逻辑判断,-O 是否是文件的拥有者(不能在双中括号中使用)
root@root:~# ls
baidunetdisk Desktop kali-sh.tar Public Videos
baidunetdiskdownload Documents Music src workspace
cmd Downloads Pictures Templates
root@root:~# [ -e cmd ] ; echo $?
0
root@root:~# test -d Downloads ; echo $?
0
root@root:~# test -d cmd; echo $?
1
root@root:~# [ -O cmd ] ;echo $?
0
root@root:~# [ -e cmd -o -e xxx ] ;echo $?
0
root@root:~# [ -e cmd -a -e xxx ] ; echo $?
1
判断字符串
-eq 等于, -ne 不等于,-n 长度不为0,-z长度为0
root@root:~# read a

root@root:~# echo $a #引用变量加双引号

root@root:~# if [ -n $a ]; then echo '长度不为0';else echo '长度为0';fi
长度不为0
root@root:~# if [ -n "$a"]; then echo '长度不为0' ; else echo '长度为0';fi
长度不为0
root@root:~# if [ "$a" ] ; then echo '不为空' ; else echo '为空'; fi
为空
root@root:~# read a
abcd
root@root:~# if [ "$a" ] ;then echo '不为空';else echo '为空';fi
不为空
[[ ]]中括号比较高级的用法,难用...
-gt 大于,-lt 小于,-ge 大于等于,-le 小于等于, -eq 等于,-ne 不等于
-n 长度不为0 , -z 长度为0, && 逻辑与,|| 逻辑或
root@root:~# [[ 23 < 123 ]] ; echo $?
1
root@root:~# [[ 23 < 24 ]] ; echo $?
0
root@root:~# a=1;b=2;c=1
#不加$符号也可以比较,尽量加上,双引号也尽量加上
root@root:~# [[ a < b ]] ;echo $?
0
root@root:~# [[ a > b ]] ; echo $?
1
root@root:~# [[ $a < $b ]] ; echo $?
0
root@root:~# [[ $a > $b ]] ; echo $?
1
root@root:~# [[ $a <= $b ]]; echo $? #这种写法报语法错误,单中括号也不能使用
bash: 条件表达式中有语法错误
bash: '$b' 附近有语法错误

root@root:~# [[ $a -lt $b ]]; echo $?
0
root@root:~# [[ $a -le $b ]]; echo $?
0
root@root:~# [[ $a = $b ]]; echo $?
1
root@root:~# [[ $a == $c ]]; echo $?
0
root@root:~# [[ $a -eq $c ]]; echo $?
0
root@root:~# [[ $a != $c ]]; echo $?
1
root@root:~# [[ $a -ne $c ]]; echo $?
1
root@root:~# [[ -n $a ]]; echo $?
0
root@root:~# declare d
root@root:~# [[ -n $d ]]; echo $?
1
root@root:~# [[ -z $d ]]; echo $?
0

root@root:~# a=mysql
root@root:~# [[ $a = mysq? ]]; echo $? #可以使用?号通配符,其它的不能使用
0
root@root:~# [[ $a == mysq? ]]; echo $?
0
root@root:~# [[ $a -eq mysql ]]; echo $? #不可以使用-eq判断非数值,以下测试都为0
0
root@root:~# [[ $a -eq mysqld ]]; echo $?
0
root@root:~# [[ $a -eq dmysql ]]; echo $?
0
root@root:~# [[ $a = worl? ]]; echo $?
1
root@root:~# [[ -n $a && 3 > 2 ]]; echo $? #逻辑与
0
root@root:~# [[ -n $a && 3 = 2 ]]; echo $?
1
root@root:~# [[ -n $a || 3 = 2 ]]; echo $? #逻辑或
0
=~ 匹配正则表达式,前者包含后者,表达式为真
^ 匹配开头,$匹配结尾
+匹配一个或多个字符, ?匹配0个或1个字符,.匹配一个字符

root@root:~# a=myddddd
root@root:~# if [[ $a =~ ^myd+ ]]; then echo 'ok';else echo 'no';fi
ok
root@root:~# if [[ $a =~ ^myd ]]; then echo 'ok';else echo 'no';fi
ok
root@root:~# if [[ $a =~ yd ]]; then echo 'ok';else echo 'no';fi
ok
root@root:~# if [[ $a =~ yds ]]; then echo 'ok';else echo 'no';fi
no
root@root:~# [[ helloword =~ word$ ]];echo $?
0
root@root:~# [[ helloword =~ wor$ ]];echo $?
1
root@root:~# [[ abc =~ a.c ]]; echo $?
0
root@root:~# [[ abc =~ a.d ]]; echo $?
1

参考资料

个人公众号,比较懒,很少更新,可以在上面提问题,如果回复不及时,可发邮件给我: tiehan@sina.cn

Sam avatar
About Sam
专注生物信息 专注转化医学