一、Bash的运算符和基本运算

1.1、 declare声明变量类型

declare格式:

declare [+/-] [选项] [变量名]

 -:给变量设定类型属性
 +:取消变量的类型属性
 
 选项:
 -a :将变量声明为数组型
 -i :将变量声明为整数型(integer)
 -x :将变量声明为环境变量    等同于: export a=100
 -r :将变量声明为只读变量
 -p :显示指定变量的被声明类型
  • 示例
# 变量声明为整数型
declare -i a=100

# 把变量定义成数组型
declare -a name[0]=zhangsan   ##定义数组,name代表数组,[0]代表下标,默认0开始,“=”后代表数组的值
declare -a name[1]=lisi
declare -a name[2]=wangwu

# 把变量定义成环境变量
declare -x test=123

# 只读变量
declare -r test

# 查看变量属性
declare -p test  
1.2、bash的运算符分类
1、算术运算符

2、关系运算符

3、布尔运算符

4、字符串运算符

5、文件测试运算符
1.2.1、算术运算符
格式1:$((算数运算符))

格式2:((表达式1,表达式2…))

格式3:[表达式]

特点:

1、在双括号结构中,所有表达式可以像c语言一样,如:a++,b--等。a++ 等价于 a=a+1 

2、在双括号结构中,所有变量可以不加入:“$”符号前缀。

3、双括号可以进行逻辑运算,四则运算

4、双括号结构 扩展了for,while,if条件测试运算((a=1,a<10,a++))

5、支持多个表达式运算,各个表达式之间用“,”分开

常用的算数运算符

运算符意义
++ --递增及递减,可前置也可以后置
+ - ! ~一元运算的 正 、负、 取反 、逻辑与
+ - * / %加减乘除与余数
< <= > >=比较大小符号
== !=相等 不相等
&& ||逻辑与 逻辑或
条件判断

Shell变量的算术运算:expr

  • 示例
# 数值计算
var1=8
var2=2
expr $var1 \* $var2

# 计算字符串长度
[root@myx~]$ expr length "hello world"
11


# 抓取字符串中特定的字串
[root@myx~]$ expr substr "hello world" 7 5
world

赋值表达式:let

格式:
 let 赋值表达式
【注】let赋值表达式功能等同于:((赋值表达式))

示例

i++	# 先赋值再自增
++i	# 先自增再赋值

i--	# 先赋值再自减
--i	# 先自减再赋值

示例:打印随机颜色

echo $RANDOM     范围0-32767

echo -e "\e[1;$[RANDOM%7+31]mhello\e[0m"

# 跑马灯名字颜色
PS1='[\[\e[$[RANDOM%7+31]m\]\u\[\[\e[$[RANDOM%7+31]m\]@\[\[\e[$[RANDOM%7+31]m\]\h\[\[\e[$[RANDOM%7+31]m\]\w]\[\[\e[$[RANDOM%7+31]m\]$ \[\[\e[$[RANDOM%7+31]m\]'
1.2.2、关系运算符

1) 关系运算符只支持数字,不支持字符串,除非字符串的值是数字。

下表列出了常用的关系运算符,假定变量 a 为 100,变量 b 为 200:

运算符说明举例
-eq检测两个数是否相等,相等返回 true。[ $a -eq $b ] 返回 false。
-ne检测两个数是否相等,不相等返回 true。[ $a -ne $b ] 返回 true。
-gt检测左边的数是否大于右边的,如果是,则返回 true。[ $a -gt $b ] 返回 false。
-lt检测左边的数是否小于右边的,如果是,则返回 true。[ $a -lt $b ] 返回 true。
-ge检测左边的数是否大等于右边的,如果是,则返回 true。[ $a -ge $b ] 返回 false。
-le检测左边的数是否小于等于右边的,如果是,则返回 true。[ $a -le $b ] 返回 true。

示例:判断是否是管理员

[root@localhost ~]# [ $(id -u) -eq 0 ] &&echo "your are admin" || echo "your are not admin"
your are admin
1.2.3、布尔运算符

1)下表列出了常用的布尔运算符,假定变量 a 为 10,变量 b 为 20:

运算符说明举例
!非运算,表达式为 true 则返回 false,否则返回 true。[ ! false ] 返回 true。
-o或运算,有一个表达式为 true 则返回 true。[ $a -lt 20 -o $b -gt 100 ] 返回 true。
-a与运算,两个表达式都为 true 才返回 true。[ $a -lt 20 -a $b -gt 100 ] 返回 false。

布尔运算符实例:

[root@localhost ~]# [ $a -lt 20 -o $b -gt 100 ] && echo yes || echo no
yes
[root@localhost ~]# [ $a -lt 20 -a $b -gt 100 ] && echo yes || echo no
no
1.2.4、字符串运算符

1)下表列出了常用的字符串运算符,假定变量 a 为 "abc",变量 b 为 "efg":

运算符说明举例
=检测两个字符串是否相等,相等返回 true。[ $a = $b ] 返回 false。
!=检测两个字符串是否相等,不相等返回 true。[ $a != $b ] 返回 true。
-z检测字符串长度是否为0,为0返回 true。[ -z $a ] 返回 false。
-n检测字符串长度是否为0,不为0返回 true。[ -n $a ] 返回 true。
str检测字符串是否为空,不为空返回 true。[ $a ] 返回 true。

2)字符串运算符示例:

[root@localhost ~]# [ $a != $b ] && echo yes || echo no
yes
1.2.5、文件测试运算符

1)文件测试运算符用于检测 Unix 文件的各种属性。

属性检测描述如下:

操作符说明举例
-b file检测文件是否是块设备文件,如果是,则返回 true。[ -b $file ] 返回 false。
-c file检测文件是否是字符设备文件,如果是,则返回 true。[ -b $file ] 返回 false。
-d file检测文件是否是目录,如果是,则返回 true。[ -d $file ] 返回 false。
-f file检测文件是否是普通文件(既不是目录,也不是设备文件),如果是,则返回 true。[ -f $file ] 返回 true。
-g file检测文件是否设置了 SGID 位,如果是,则返回 true。[ -g $file ] 返回 false。
-k file检测文件是否设置了粘着位(Sticky Bit),如果是,则返回 true。[ -k $file ] 返回 false。
-p file检测文件是否是具名管道,如果是,则返回 true。[ -p $file ] 返回 false。
-u file检测文件是否设置了 SUID 位,如果是,则返回 true。[ -u $file ] 返回 false。
-r file检测文件是否可读,如果是,则返回 true。[ -r $file ] 返回 true。
-w file检测文件是否可写,如果是,则返回 true。[ -w $file ] 返回 true。
-x file检测文件是否可执行,如果是,则返回 true。[ -x $file ] 返回 true。
-s file检测文件是否为空(文件大小是否大于0),不为空返回 true。[ -s $file ] 返回 true。
-e file检测文件(包括目录)是否存在,如果是,则返回 true。[ -e $file ] 返回 true。
-L file检测文件是否是链接文件,是否有效,如果是,则返回 true。[ -L $file ] 返回 true。

示例

# 判断文件是否存在
[root@localhost ~]# [ -e a ]     ##用于判断a文件是否存在,存在则为真(0)
[root@localhost ~]# echo $?
0
[root@localhost ~]# [ -e abc ]   ##判断abc文件是否存在,不存在则为假(1)
[root@localhost ~]# echo $?
1

# 判断是否是链接文件 是否有效
[root@localhost ~]# touch file1.txt

[root@localhost ~]# ln -s file1.txt file1.txt.bak

[root@localhost ~]# [ -e file1.txt.bak -a -L file1.txt.bak ]&&echo yes || echo no
yes

2)两个文件之间进行比较

文件1 -nt 文件2   判断文件1修改的时间是否比文件2的新,如果新则为真

文件1 -ot 文件2   判断文件1修改的时间是否比文件2的旧,如果旧则为真

文件1 -ef 文件2    判断文件1和文件2的INODE号是否一致,如果一致则为真

3) 变量测试判断

-v VAR_NAME    ##判断变量是否被定义

注:只判断该变量是否被定义,所以即使定义的是空值也为 真

示例:

[root@localhost ~]# [ -v b ] && echo yes || echo no  ##b变量已经被定义,则为真
yes
[root@localhost ~]# [ -v c ] && echo yes || echo no   ##c变量没有被定义,则为假
no
1.3、 [[ ]]的应用
1.3.1 示例1:对空值的判断区别

[ ] 无法使用通配符和正则表达式,但是[[ ]]是可以匹配通配符和正则表达式

[root@localhost ~]# [ "$name" = hello ]&& echo yes ||echo no
no
[root@localhost ~]# [[ $name = hello ]]&& echo yes ||echo no
no

注意:“==”表示通配符,“=~”表示正则表达式

1.3.2 [[ ]]示例:通配符和正则判断
##通配符
[root@localhost ~]# name=file.txt

[root@localhost ~]# [[ "$name" == *.txt ]] && echo yes || echo no
yes
[root@localhost ~]# [[ "$name" == *.log ]] && echo yes || echo no
no
[root@localhost ~]# [[ "$name" != *.log ]] && echo yes || echo no
yes
##正则表达式

##匹配.log结尾
[root@localhost ~]# name=file.txt

[root@localhost ~]# [[ "$name" =~ \.log$ ]] && echo yes || echo no
no
[root@localhost ~]# [[ "$name" =~ \.txt$ ]] && echo yes || echo no
yes


##匹配数字结尾
[root@localhost ~]# num=10
[root@localhost ~]# [[ "$num" =~ ^[0-9]+$ ]] &&echo yes || echo no
yes

##匹配字母结尾
[root@localhost ~]# num1=10a
[root@localhost ~]# [[ "$num1" =~ ^[a-z]$ ]] &&echo yes || echo no
no
[root@localhost ~]# [[ "$num1" =~ [a-z]+$ ]] &&echo yes || echo no
yes

##匹配数字结尾
[root@localhost ~]# num2=a10
[root@localhost ~]# [[ "num2" =~ [0-9]+$ ]] &&echo yes || echo no
yes

##匹配IP地址
[root@localhost ~]# ip=192.168.1.1

[root@localhost ~]# [[ "$ip" =~ ^([0-9]{1,3}.){3}[0-9]{1,3}$ ]] && echo yes || echo no
yes


[root@localhost ~]# ip=1111.2222.2222.111a
[root@localhost ~]# [[ "$ip" =~ ^(([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$ ]] && echo yes || echo no
no

[root@localhost ~]# ip=1111.2222.2222.1119
[root@localhost ~]# [[ "$ip" =~ ^(([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$ ]] && echo yes || echo no
no

[root@localhost ~]# ip=1.22.2.111
[root@localhost ~]# [[ "$ip" =~ ^(([1-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$ ]] && echo yes || echo no
yes

##另一种写法
[root@localhost ~]# [[ "$ip" =~ ^(([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$ ]] && echo yes || echo no
yes
1.3.2 关于[[ == ]]双等(==)号右边的双引号的说明:

示例:

[root@localhost ~]# name=wcfeng123
[root@localhost ~]# [[ "$name" == wcfeng* ]] && echo yes || echo no
yes
[root@localhost ~]# [[ "$name" == "wcfeng*" ]] && echo yes || echo no
no
[root@localhost ~]# [[ "$name" == wcfeng\* ]] && echo yes || echo no
no
1.4、 {}和()的区别

( ):在小括号中定义的变量的值将不会影响父shell中定义的变量的值 { }: 在花括号中定义的变量的值将会影响父shell中定义的变量的值

# 小括号写法
(echo $name)

# 大括号写法
{ echo $name; }

 ##注意{}的写法,在{ 后需要加空格,在}之前也需要空格,并加;结束

拓展

  • 判断服务器的根分区的使用率是否超过80%,如果超过了,则给自己的邮箱发一份邮件

邮件服务部署脚本

#!/bin/bash

DISK_USED=`df -h | grep "/$" | tr -s ' ' | cut -d' ' -f5 | grep -o [0-9]*`

[ "$DISK_USED" -ge 30 ] && echo "你的磁盘占用已经达到"$DISK_USED%",请及时清理
!" | mail -s '磁盘告急' 2041598918@qq.com