元字符
元字符指的是能够被shell解释的特殊字符,每个特殊字符都有其特殊含义,这些字符一方面可用于变量值的运算、我们可以称之为运算符,另外一方面可以和shell命令配合使用来达到更高级的效果
算数运算符
算数运算符需要配合下述操作使用
# 浮点运算
bc
# 整数运算
expr
$(())
$[]
let
bc是比较常用的linux计算工具了,而且支持浮点运算
[root@m01 ~]# res=`echo 1+1 | bc`
[root@m01 ~]# echo $res
2
[root@m01 ~]# res=`echo 10 % 3| bc` % 取余数
[root@m01 ~]# echo $res
1
[root@m01 ~]# res=`echo 1.2+1.3|bc`
[root@m01 ~]# echo $res
2.5
[root@m01 ~]# res=`echo 5.0+3.0|bc`
[root@m01 ~]# echo $res
8.0
[root@m01 ~]# res=`echo "scale=2;5.0/3.0"|bc` / 除(取相除后的值,scale=2保留两位小数)
[root@m01 ~]# echo $res
1.66
[root@m01 ~]# res=`echo "scale=3;5.0/6.0"|bc` / 除(取相除后的值,scale=3保留三位小数)
[root@m01 ~]# echo $res
.833
expr不支持浮点数计算,而且要注意数字与运算符中的空格
[root@m01 ~]# res=`expr 5 / 3` # 不支持浮点计算
[root@m01 ~]# echo $res
1
[root@m01 ~]# res=`expr 1+1` # 注意:要有空格
[root@m01 ~]# echo $res
1+1
[root@m01 ~]# res=`expr 1 + 1`
[root@m01 ~]# echo $res
2
如果是乘法,需要转义\*
[root@m01 ~]# expr 3 \* 10
30
$(( )) 同expr,不支持浮点数运算
[root@m01 ~]# echo $((1+1))
2
[root@m01 ~]# echo $((1.0+1.0)) $(())不支持浮点数运算
-bash: 1.0+1.0: syntax error: invalid arithmetic operator (error token is ".0+1.0")
# 注意:
echo $(($num1+$num2)) # 也可以简写为 echo $((num1+num2))
echo $(((5-3)*2)) # 可以嵌套括号
let 不支持浮点数运算,而且不支持直接输出,只能赋值
[root@m01 ~]# let res=1+1
[root@m01 ~]# echo $res
2
[root@m01 ~]# let res=10/2
[root@m01 ~]# echo $res
5
[root@m01 ~]# let c=1.3*3
-bash: let: c=1.3*3: syntax error: invalid arithmetic operator (error token is ".3*3")
算数运算符练习题
计算器,可实现加减乘除
vim test.sh
#!/bin/bash
read -p "输入数字" num1
read -p "输入运算符" symbol
read -p "输入数字" num2
NUM=`echo $num1 $symbol $num2 | bc`
echo $NUM
实现2位数加减乘除运算
vim a.sh
#!/bin/bash
a=$1
b=$2
# $#输入参数的个数 , -ne不等于
[ $# -ne 2 ] && {
echo "请输入两位数字信息"
exit
}
echo "a-b=$(($a-$b))"
echo "a+b=$(($a+$b))"
echo "a*b=$(($a*$b))"
echo "a/b=$(($a/$b))"
编写判断输入参数是否是整数信息
vim test01.sh
#!/bin/bash
a=$1
# 只有整型加0才不会报错,浮点数及字符与0相加都会报错
expr $a + 0 &> /dev/null
[ $? -eq 0 ] && echo "输入的是整数信息" || echo "输入的是非整数信息"
如何利用脚本计算1+2+3+4..10总和数值
python写法
a = 0
b = 1
while True:
if b <= 10:
a = a + b
b = b + 1
else:
print(a)
break
如何利用脚本计算1+2+3+4..10总和数值
shell写法
方法一:
seq -s "+" 10|bc
[root@m01 ~]# seq -s "+" 10
1+2+3+4+5+6+7+8+9+10
方法二:
echo {1..10}|tr " " "+"|bc
[root@m01 ~]# echo {1..10}|tr " " "+"
1+2+3+4+5+6+7+8+9+10
方法三:
awk 'BEGIN{for (i=1; i<=10; i++) a=a+i; print a}'
测试运算符
测试命令:test,详细可用man test查询
测试符号:[ ],注意只有一层中括号,中括号内左右两侧必须要有空格
test与[]效果都一样,参数也都一样
测试文件状态
-d 判断是否是目录
[root@m01 ~]# test -d /etc/;echo $?
0
[root@m01 ~]# [ -d /etc/ ];echo $? # 注意[]内左右两侧要有空格
0
-s 判断文件内容长度>0、非空
[root@m01 ~]# echo 123 > a.txt
[root@m01 ~]# test -s a.txt;echo $?
0
[root@m01 ~]# [ -s a.txt ];echo $?
0
-f 判断文件属性标准文件
[root@m01 ~]# test -f /etc/passwd;echo $?
0
[root@m01 ~]# [ -f /etc/passwd ];echo $?
0
-w 可写
[root@m01 ~]# chmod a-w a.txt
[root@m01 ~]# su - nana
[nana@m01 ~]$ [ -w a.txt ];echo $? # 返回假,注意,如果是root用户,无论如何都有写权限
1
[nana@m01 ~]$ test -w a.txt;echo $?
1
-r 可读
[root@m01 ~]# ll a.txt
-r--r--r-- 1 root root 4 Jun 17 15:11 a.txt
[root@m01 ~]# test -r a.txt;echo $?
0
[root@m01 ~]# [ -r a.txt ];echo $?
0
-x 可执行
[root@m01 ~]# ll a.txt
-r--r--r-- 1 root root 4 Jun 17 15:11 a.txt
[root@m01 ~]# test -x a.txt;echo $?
1
[root@m01 ~]# [ -x a.txt ];echo $?
1
-L 符号连接(判断是否是软链接)
[root@m01 ~]# ll -d /lib
lrwxrwxrwx. 1 root root 7 Apr 19 23:46 /lib -> usr/lib
[root@m01 ~]# [ -L /lib ];echo $?
0
[root@m01 ~]# test -L /lib;echo $?
0
-u 文件有suid位设置(ACL权限设置)
[root@m01 ~]# ll /usr/bin/passwd
-rwsr-xr-x. 1 root root 27856 Apr 1 2020 /usr/bin/passwd
[root@m01 ~]# [ -u /usr/bin/passwd ];echo $?
0
[root@m01 ~]# test -u /usr/bin/passwd;echo $?
0
-c 判断是否是磁盘文件
[root@m01 ~]# test -c /dev/null;echo $?
0
[root@m01 ~]# [ -c /dev/null ];echo $?
0
字符串测试
== 两个字符串相等
[root@m01 ~]# [ "AAA" == "AAA" ];echo $?
0
!= 两个字符不相等
[root@m01 ~]# [ "AAA" != "AAA" ];echo $?
1
-z 字符长度为零
[root@m01 ~]# ip=" "
[root@m01 ~]# [ -z "$ip" ];echo $? # 注意引号
0
[root@m01 ~]# ip="1.1.1.1"
[root@m01 ~]# test -z "$ip";echo $?
1
-n 字符串长度不为零
[root@m01 ~]# a=
[root@m01 ~]# [ -n "$a" ];echo $? # 注意加引号
1
测试数值
test与[ ]也可以测试数值,与 [[ ]]和(( ))效果一样
- -eq 等于
- -ne 不等于
- -gt 大于
- -lt 小于
- -ge 大于等于
- -le 小于等于
- -a 并且
- -o 或者
[root@m01 ~]# [ 10 -eq 10 ];echo $?
0
[root@m01 ~]# [ 10 -eq 10 -a 10 > 3 ];echo $?
0
示例1
[root@m01 ~]# disk_use=`df -P | grep "/boot$" | awk '{print $5}' | awk -F% '{print $1}'`
[root@m01 ~]# echo disk_use
disk_use
[root@m01 ~]# echo $disk_use
14
[root@m01 ~]# [ $disk_use -gt 10 ] && echo "warn..."
warn...
示例2
[root@m01 ~]# [ $(id -u) -eq 0 ] && echo "当前是超级用户" || echo "you不是超级用户"
当前是超级用户
关系运算符
<
>
<=
>=
==
!=
&&
||
上述关系运算符需要配合(( ))使用(注意(( ))属于C语言风格的比较),最终都是用来当if判断或者while循环的条件
[root@m01 ~]# x=100
[root@m01 ~]# (($x > 10));echo $?
0
[root@m01 ~]# (($x < 10));echo $?
1
[root@m01 ~]# (($x == 100));echo $?
0
[root@m01 ~]# (($x != 100));echo $?
1
[root@m01 ~]# (($x != 100)) || (("nana" == "nana"))
[root@m01 ~]# echo $?
0
[root@m01 ~]# (($x != 100)) && (("lala" == "lala"))
[root@m01 ~]# echo $?
1
[root@m01 ~]# (($x != 100 || "nana" == "nana"))
[root@m01 ~]# echo $?
0
[root@m01 ~]# (($x != 100 && "nana" == "nana"))
[root@m01 ~]# echo $?
1
赋值运算符
=
[root@m01 ~]# x=10
[root@m01 ~]# echo $x
10
+=
[root@m01 ~]# x=10
[root@m01 ~]# ((x+=10))
[root@m01 ~]# echo $x
20
*=
[root@m01 ~]# x=10
[root@m01 ~]# ((x*=2))
[root@m01 ~]# echo $x
20
/=
[root@m01 ~]# x=10
[root@m01 ~]# ((x/=2))
[root@m01 ~]# echo $x
5
%=
[root@m01 ~]# x=10
[root@m01 ~]# ((x%=3))
[root@m01 ~]# echo $x
1
[[ ]]
[[ ]]与[ ]基本一样,不同的是[[ ]]支持正则匹配,不过要注意的是必须在内层中括号内左右两侧加空格
[root@m01 ~]# user=root
[root@m01 ~]# [[ "$user" == "root" ]];echo $? # 注意内层[]中包含的内容必须左右两侧加空格
0
[root@m01 ~]# [[ "$user" = "root" ]];echo $? # 一个等号也行两个等号也可以
0
此外[[ ]]内部是可以使用正则的,注意:正则表达式不要加引号
[root@m01 ~]# [[ "$user" =~ "^root$" ]];echo $? # 正则表达式不要加引号
1
[root@m01 ~]# [[ "$user" =~ ^root$ ]];echo $? # 正则表达式不要加引号
0
[root@m01 ~]# [[ ! "$user" =~ ^root$ ]] && echo 此时登陆的不是管理员 || echo 是管理员啊
是管理员啊
[root@m01 ~]# num1=123
[root@m01 ~]# [[ "$num1" =~ ^[0-9]+$ ]];echo $?
0
[root@m01 ~]# [[ "$num1" =~ ^[0-9]+$ ]];echo "数字"
数字
传入两个数值信息, 自动让脚本显示数值比较情况
- 整数比较
vim num.sh
#!/bin/bash
[ $# -ne 2 ] && echo "只能传入两个整数" && exit
[[ ! $1 =~ ^[0-9]+$ ]] && echo "参数1必须是整数" && exit
[[ ! $2 =~ ^[0-9]+$ ]] && echo "参数2必须是整数" && exit
方式一:
# [[ $1 -lt $2 ]] && echo "$1 < $2"
# [[ $1 -gt $2 ]] && echo "$1 > $2"
# [[ $1 -eq $2 ]] && echo "$1 = $2"
方式二:
(( $1 < $2 )) && echo "$1 < $2"
(( $1 > $2 )) && echo "$1 > $2"
(( $1 == $2 )) && echo "$1 = $2"
- 浮点数的比较 # 需要注意的是: bc的结果为1代表真,为0代表假
[root@m01 ~]# echo "10.3 >= 10.1" | bc
1
[root@m01 ~]# echo "10.3 != 10.1" | bc
1
[root@m01 ~]# x=10.3
[root@m01 ~]# y=10.1
[root@m01 ~]# [ `echo "$x >= $y" | bc` -eq 1 ]&& echo "$x > $y" 需要注意的是: bc的结果为1代表真,为0代表假
10.3 > 10.1
[root@m01 ~]# (( `echo "$x >= $y" | bc` == 1 ))&& echo "$x > $y" 需要注意的是: bc的结果为1代表真,为0代表假
10.3 > 10.1
其他元字符
> 1、`` 与$() 取命令的结果
> 2、~家目录
> 3、.与..
> 4、!调用历史命令、取反
> 5、@无特殊意义
> 6、#注释
> 7、$取变量值
> 8、%、-、+运算符,注意%可以与jobs配合“kill %工作号”杀后台进程。-减号还有区间及cd -回到上一级的意思
> 9、^同!一样
> 10、&后台运行
> 11、*任意多个字符
> 12、()在子shell中执行
> 13、_下划线:无特殊意义,可以用于名字的声明
> 14、=赋值,==判断相等性
> 15、|管道:把一个进程的处理结果传递给另外一个进程
> 16、\转义特殊字符
> 17、[]条件测试
> 18、 '' 强引用(在单引号中都视为普通字符) " " 弱引用 (在双引号中保留变量)
> 19、;与&&与||连接多条命令
> 20、:空命令,真值
> 21、/路径分隔符
> 22、{}循环列表
> 23、> >> 输出重定向 < << 输入重定向
> 24、?任意一个字符
> 25、范围中的任意一个字符 ls a[A-Z]c # 不区分大小写 ls a[0-9]c