Bash 基本运算和变量

注意:变量尽量用双引号引起来
对于值为非空的变量无所谓,对于值为空的变量,很可能出问题

一、expr 为内置命令,只对整数进行运算(注意空格)

1.1 四则运算(只有 + - * / % ± 这些符号可用)

zds@ubuntu:~$ expr 8 + 9
17
zds@ubuntu:~$ expr -9 + 3
-6
zds@ubuntu:~$ expr 3 \* 22  # 乘号需转义
66
zds@ubuntu:~$ expr 22 % 9  # 取余数
4
zds@ubuntu:~$ expr 123 / 12 - 3
7
zds@ubuntu:~$ a=5
zds@ubuntu:~$ expr $a / -2
-2

1.2 逻辑运算:或 |&!(前两者须转义,后者须配合 = 使用)
注意命令的返回值(即运算结果)和退出状态码的区别

zds@ubuntu:~$ expr 9 \| 3  # 两者都不为 0 结果取前者,退出状态码为 0
9
zds@ubuntu:~$ expr 3 \| 9
3
zds@ubuntu:~$ expr 0 \| 0  # 若两个都为 0 结果为 0,退出状态码为 1
0
zds@ubuntu:~$ expr 0 \| 5  # 若有一个为 0 结果取另一个的值,退出状态码为 0
5
zds@ubuntu:~$ expr 5 \| 0
5
zds@ubuntu:~$ expr 4 \& 9  # 两者都不为 0 结果取前者,退出状态码为 0
4
zds@ubuntu:~$ expr 9 \& 4
9
zds@ubuntu:~$ expr 0 \& 0  # 两者若有一个为 0 结果即为 0,退出状态码为 1
0
zds@ubuntu:~$ expr 111 \& 0
0
zds@ubuntu:~$ expr 0 \& 111
0
zds@ubuntu:~$ expr 9 != 3  # 逻辑为真结果是 1,退出状态码为 0
1
zds@ubuntu:~$ expr 9 != 7 + 2  # 逻辑为假结果是 0,退出状态码为 1
0
zds@ubuntu:~$ expr 9 = 3 \* 3  # 逻辑为真结果是 1,退出状态码为 0
1

1.3 关系运算<> 须转义)
注意:下面说的都是运算结果(即命令返回值),而不是退出状态码

zds@ubuntu:~$ expr 9 \< 9  # 关系为假结果是 0
0
zds@ubuntu:~$ expr 8 \>= 3 \* 3
0
zds@ubuntu:~$ expr 8 \>= 2 \* 3  # 关系为真结果是 1
1
zds@ubuntu:~$ expr -45 / 11 = -4  # 一个等号和俩等号都是判断左右是否相等
1
zds@ubuntu:~$ expr 3 == 3  # macOS 中不能使用俩等号
1

二、(( )) 依然只对整数进行运算

相较 expr 要人性化,不必转义特殊符号,不必加空格

zds@ubuntu:~$ ((a=(2+3)*4))  # 可用使用括号
zds@ubuntu:~$ echo $a
20
zds@ubuntu:~$ a=0
zds@ubuntu:~$ echo $a
0
zds@ubuntu:~$ ((a+=3))
zds@ubuntu:~$ echo $a
3
zds@ubuntu:~$ ((a=a*4))
zds@ubuntu:~$ echo $a
12
zds@ubuntu:~$ ((a/=5))
zds@ubuntu:~$ echo $a
2
zds@ubuntu:~$ ((a++))  # 加 1
zds@ubuntu:~$ echo $a
3
zds@ubuntu:~$ ((a--))  # 减 1
zds@ubuntu:~$ echo $a
2
zds@ubuntu:~$ echo $((9*-4/6))  # 固定写法
-6
zds@ubuntu:~$ echo $((3**4))  # 幂运算
81
zds@ubuntu:~$ echo $((2#101))  # 把井号后面的数当作二进制来处理,将之转换为十进制
5

三、let(( )) 一样

zds@ubuntu:~$ a=0
zds@ubuntu:~$ let a-=9
zds@ubuntu:~$ echo $a
-9
zds@ubuntu:~$ let a=(89-33)*7
zds@ubuntu:~$ echo $a
392

四、declare -i 使变量数值化

zds@ubuntu:~$ num=2+3
zds@ubuntu:~$ echo $num
2+3
zds@ubuntu:~$ declare -i num  # 使 num 变量的值数值化
zds@ubuntu:~$ echo $num
2+3
zds@ubuntu:~$ num=9/4
zds@ubuntu:~$ echo $num
2
zds@ubuntu:~$ num=ok  # 赋值字符串,无法计算,结果为 0
zds@ubuntu:~$ echo $num
0

五、bc 属于外部命令,可用 sudo apt install bc 安装

5.1 bc 可运算小数
结果小数位数等于算术式中数值的小数位数的最大值

zds@ubuntu:~$ echo '2+2' | bc
4
zds@ubuntu:~$ echo '(3+2.4)*7' | bc  
37.8
zds@ubuntu:~$ echo '(-36%7)**3--5.5' | bc  # 不可连续两个减号
(standard_in) 1: syntax error
zds@ubuntu:~$ echo '(-36%7)**3-(-5.5)' | bc  # 不可进行幂运算
(standard_in) 1: syntax error
zds@ubuntu:~$ echo '(-36%7)*3-(-5.5)' | bc
2.5

5.2 交互界面,按 Ctrl + D 退出

zds@ubuntu:~$ bc
bc 1.06.95
Copyright 1991-1994, 1997, 1998, 2006 Free Software Foundation, Inc.
This is free software with ABSOLUTELY NO WARRANTY.
For details type `warranty'. 
(8*8-9)/3.3
16
scale=2  # 默认保留 0 位小数,设置小数位数为 2,只对乘除有效
(8*8-9)/3.3
16.66

六、条件判断

6.1 Shell 中的 test 命令用于检查某个条件是否成立,它可以进行数值、字符和文件三个方面的测试

6.1.1 test 比较两个整数值,[ ] 等同于 test,注意只能比较一位数
-gt \> 大于,-lt \< 小于,-ge 大于等于,-le 小于等于
-eq = == 等于,-ne != 不等于:

mcdx@ubuntu:~$ test 2 -gt 3  
mcdx@ubuntu:~$ echo $?  # 获取上次命令的返回值,结果为假返回值为 1
1
mcdx@ubuntu:~$ test 34 -lt 91
mcdx@ubuntu:~$ echo $?  
0
mcdx@ubuntu:~$ [ 3 -eq 3 ]
mcdx@ubuntu:~$ echo $?
0
mcdx@ubuntu:~$ read a b
1 1
mcdx@ubuntu:~$ if [ $a == $b ]; then echo '俩数相等'; fi
俩数相等
mcdx@ubuntu:~$ read a b 
1 2
mcdx@ubuntu:~$ if [ $a -le $b ]; then echo 'a 小于等于 b'; fi
a 小于等于 b
mcdx@ubuntu:~$ read a b
1 '1'
mcdx@ubuntu:~$ if [ $a = $b ]; then echo '俩数相等'; else echo '俩数不等'; fi
俩数不等

6.1.2 test [ ] 判断字符串
-eq = == 等于,-ne != 不等于,-n 长度不为零,-z 长度为零:

mcdx@ubuntu:~$ read a

mcdx@ubuntu:~$ echo $a  # 体现了引用变量加双引号的重要性

mcdx@ubuntu:~$ if [ -n $a ]; then echo '长度不为零'; else echo '长度为零'; fi
长度不为零
mcdx@ubuntu:~$ if [ -n "$a" ]; then
> echo '长度不为零'; else
> echo '长度为零'; fi
长度为零
mcdx@ubuntu:~$ read a

# -n 可省略
mcdx@ubuntu:~$ if [ "$a" ]; then echo '不为空'; else echo '为空'; fi  
为空  
mcdx@ubuntu:~$ read a
12
mcdx@ubuntu:~$ if [ "$a" ]; then echo '不为空'; else echo '为空'; fi
不为空

6.1.3 test [ ] 判断文件
-d 是目录,-e 文件存在,-r 文件可读,-w 文件可写,-x 文件可执行
-f 普通文件,-s 文件大小不为零,-o 或逻辑,-a 与逻辑
-O 当前用户是文件的拥有者(以上这些,双中括号不能用):

mcdx@ubuntu:~$ ls
Desktop  Documents  Downloads  git  simpledu  test  test.sh
mcdx@ubuntu:~$ [ -e test.sh ]; echo $?
0
mcdx@ubuntu:~$ test -d git; echo $?
0
mcdx@ubuntu:~$ test -d test.sh; echo $?
1
mcdx@ubuntu:~$ [ -O test.sh ]; echo $?
0
mcdx@ubuntu:~$ [ -e test.sh -o -e xxx ]; echo $?
0
mcdx@ubuntu:~$ [ -e test.sh -a -e xxx ]; echo $?
1

6.2 [[ ]] 是比较高级的判断方法(说是高级,其实用法之复杂也让人作呕)
-gt > 大于,-lt < 小于(<> 只能比较一位数字的大小)
-ge 大于等于,-le 小于等于,-eq = == 等于,-ne != 不等于
-n 长度不为零,-z 长度为零,&& 与,|| 或:

shiyanlou:~/ $ [[ 23 < 123 ]]; echo $?  
1
shiyanlou:~/ $ [[ 23 < 24 ]]; echo $?  
0
zds@ubuntu:~$ a=1; b=2; c=1
# 不加 $ 符号也可以,但尽量加上,双引号也尽量加上
zds@ubuntu:~$ [[ a < b ]]; echo $?  
0
zds@ubuntu:~$ [[ a > b ]]; echo $?
1
zds@ubuntu:~$ [[ $a < $b ]]; echo $?
0
zds@ubuntu:~$ [[ $a > $b ]]; echo $?
1
zds@ubuntu:~$ [[ $a <= $b ]]; echo $?  # 这种写法不行,单中括号里也不行
bash: 条件表达式中有语法错误
bash: `$b' 附近有语法错误
zds@ubuntu:~$ [[ $a -lt $b ]]; echo $?
0
zds@ubuntu:~$ [[ $a -le $b ]]; echo $?
0
zds@ubuntu:~$ [[ $a = $c ]]; echo $?
0
zds@ubuntu:~$ [[ $a = $b ]]; echo $?
1
zds@ubuntu:~$ [[ $a == $c ]]; echo $?
0
zds@ubuntu:~$ [[ $a -eq $c ]]; echo $?
0
zds@ubuntu:~$ [[ $a != $c ]]; echo $?
1
zds@ubuntu:~$ [[ $a -ne $b ]]; echo $?
0
zds@ubuntu:~$ [[ -n $a ]]; echo $?
0
zds@ubuntu:~$ declare d
zds@ubuntu:~$ [[ -n $d ]]; echo $?
1
zds@ubuntu:~$ [[ -z $d ]]; echo $?
0
zds@ubuntu:~$ e=hello
zds@ubuntu:~$ [[ $e = hell? ]]; echo $?  # 问号通配符也能用(别的通配符不行)
0
zds@ubuntu:~$ [[ $e == hell? ]]; echo $?
0
zds@ubuntu:~$ [[ $e -eq hello ]]; echo $?  # 不可以用 -eq 判断非数值
0
zds@ubuntu:~$ [[ $e -eq hellooo ]]; echo $?
0
zds@ubuntu:~$ [[ $e = worl? ]]; echo $?
1
zds@ubuntu:~$ [[ -n $e && 3 > 2 ]]; echo $?  # 与
0
zds@ubuntu:~$ [[ -n $e && 3 = 2 ]]; echo $?
1
zds@ubuntu:~$ [[ -n $e || 3 = 2 ]]; echo $?  # 或
0

=~ 使用正则表达式,前者包含后者,表达式即为真。几个常用的符号:
^ 匹配字符串的开始处,$ 匹配字符串的结尾处
+ 匹配一个或多个前面的字符,? 匹配 0 个或 1 个前面的字符
. 匹配任意一个字符

mcdx@ubuntu:~$ a=assss
mcdx@ubuntu:~$ if [[ $a =~ ^as+ ]]; then echo 'ok'; else echo 'not ok'; fi
ok
mcdx@ubuntu:~$ if [[ $a =~ ^as ]]; then echo 'ok'; else echo 'not ok'; fi
ok
mcdx@ubuntu:~$ if [[ $a =~ ss ]]; then echo 'ok'; else echo 'not ok'; fi
ok
mcdx@ubuntu:~$ if [[ $a =~ sst ]]; then echo 'ok'; else echo 'not ok'; fi
not ok
mcdx@ubuntu:~$ [[ helloworld =~ world$ ]]; echo $?
0
mcdx@ubuntu:~$ [[ helloworld =~ worl$ ]]; echo $?
1
mcdx@ubuntu:~$ [[ abc =~ a.c ]]; echo $?
0
mcdx@ubuntu:~$ [[ abc =~ a.d ]]; echo $?
1

七、随机数

7.1 $RANDOM 可以生成 0-32767 的随机数
它不是一个变量,是一个内置的函数:

mcdx@ubuntu:~$ echo $RANDOM
32058
mcdx@ubuntu:~$ echo $RANDOM
170
mcdx@ubuntu:~$ echo $RANDOM
17302
mcdx@ubuntu:~$ expr $RANDOM / 222
54

7.2 此外,还可以使用 shuf 生成随机数
-i 指定随机数值的范围,-n 指定随机数的数量

mcdx@ubuntu:~$ shuf -i 1-10 -n 3
1
9
2
mcdx@ubuntu:~$ shuf -i 100-1000 -n 4
835
460
454
599
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,907评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,987评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,298评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,586评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,633评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,488评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,275评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,176评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,619评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,819评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,932评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,655评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,265评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,871评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,994评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,095评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,884评论 2 354

推荐阅读更多精彩内容