Shell编程符号学习
退出状态
★进程使用退出状态来报告成功或失败
◆0 代表成功,1-255代表失败
◆$? 变量保存最近的命令退出状态 (查看:echo $?)存的是最后一条命令的结果,中间即使有错误,也不管。
★脚本的状态返回值
◆默认是脚本中执行的最后一条命令的状态返回值;
◆自定义状态退出状态码;
exit[n]:自定义退出状态码;(exit退出的是当前shell)
注意:
脚本中一旦遇到exit命令,脚本会立即终止;终止退出状态取决于exit命令后面的数字
如果未给脚本指定退出状态码,整个脚本的退出状态码取决于脚本中执行的最后一条命令的状态码
演示:
1.进程使用退出状态
|
1
2
3
4
5
6
7
8
9
|
-c1代表一个数据包,-W代表一秒钟[root@Miskey ~]# ping -c1 -W1 10.0.0.11116 &> /devnull[root@Miskey ~]# echo $?0 # 成功,此主机正在使用[root@Miskey ~]# ping -c1 -W1 10.0.0.11112 &> /devnull[root@Miskey ~]# echo $?1 # 失败,此主机没有使用 |
条件测试
★作用:
判断某需求是否满足,需要由测试机制来实现;
专用的测试表达式需要由测试命令辅助完成测试过程;
★如何编写测试表达式以实现所需的测试:
☉执行命令,并利用状态返回值来判断:
0:成功
1-255:失败
☉测试表达式:
test EXPRESSION;
[ EXPRESSION ];
` EXPRESSION `;特定情况下使用。最稳妥(支持正则表达式)
注意:
EXPRESSION前后必须有空白字符,否则语法错误。
★条件性的执行逻辑操作符
☉根据退出状态而定,命令可以有条件地运行
&& :代表条件性的AND THEN;
|| :代表条件性的OR ELSE
演示:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
[root@Miskey ~]# ping -c1 -W1 10.0.0.111 &> /dev/null && echo "The host is up"The host is up# 表示 如果能 ping 通这个主机 就输出 up,不能就输出 down;一定是先与后或[root@Miskey ~]# ping -c1 -W1 10.0.0.111 &> /dev/null && echo "The host is up" || echo "The host is down"The host is up[root@Miskey ~]# ping -c1 -W1 10.0.0.11114 &> /dev/null && echo "The host is up" || echo "The host is down"The host is down# 表示 如果能 ping 通这个主机 就输出 up,不能就输出 down,且返回值为 220。这里的括号表示在子shell中执行[root@Miskey ~]# ping -c1 -W1 10.0.0.11114 &> /dev/null && echo "The host is up" || (echo "The host is down" ;exit 220)The host is down[root@Miskey ~]# echo $?220 |
bash的测试类型(数值,字符串,文件测试)
1.数值测试
★数值测试
☉作用:数值比较
☉操作符
-eq:是否等于;[ $num1 -eq $num2 ];
-ne:是否不等于;
-gt:是否大于;
-ge:是否大于等于;
-lt:是否小于;
-le:是否小于等于;
演示:
|
1
2
3
4
5
6
7
8
9
10
11
12
|
[root@Miskey ~]# test 2 -eq 3[root@Miskey ~]# echo $?1[root@Miskey ~]# test 2 -ne 3[root@Miskey ~]# echo $?0[root@Miskey ~]# test 2 -gt 3[root@Miskey ~]# echo $?1[root@Miskey ~]# test 2 -lt 3[root@Miskey ~]# echo $?0 |
2.字符串测试
★字符串测试
字符串比较要加引号;
尽量要使用` `
☉操作符
==:是否等于;
>:ascii码是否大于ascii码;
<:ascii码是否小于ascii码
!=:是否不等于;
=~:左侧字符串是否能够被右侧的PATTERN所匹配(扩展表达式)
-z "STRING":判断指定的字符串是否为空,空为真,不空为假,字符串一定要加双引号;
-n "STRING":判断指定的字符串是否不空,不空为真,空为假;
注意:
字符串比较要加引号,表示引用,做变量替换要加双引号,不做变量替换用单引号;
要尽量使用 ` `
在 [ ] 中做变量替换一定要加双引号,但是如果使用 ` ` ,可以不加引号
演示:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
|
[root@Miskey ~]# [ tom == Tom ][root@Miskey ~]# echo $?1[root@Miskey ~]# [ tom == tom ][root@Miskey ~]# echo $?0# 变量替换要尽量用双引号,如果不用的话,如果变量不存在为空,会报错[root@Miskey ~]# [ tom == $name ]-bash: [: tom: 期待一元表达式[root@Miskey ~]# [ tom == "$name" ] [root@Miskey ~]# echo $?1[root@Miskey bin]# [[ tom == $name ]][root@Miskey bin]# echo $?1[root@Miskey ~]# name=xiu[root@Miskey ~]# [ tom == $name ][root@Miskey ~]# echo $?1[root@Miskey ~]# [ tom == "$name" ][root@Miskey ~]# echo $?1# 要尽量使用 [[ ]][root@Miskey ~]# [ 'a' > 'b' ][root@Miskey ~]# echo $?0[root@Miskey ~]# [ 'a' < 'b' ][root@Miskey ~]# echo $?0[root@Miskey ~]# [[ 'a' > 'b' ]][root@Miskey ~]# echo $?1[root@Miskey ~]# [[ 'a' < 'b' ]][root@Miskey ~]# echo $?0# 在 [] 中变量替换一定要加双引号,但是在 [[ ]] 中可以不加[root@Miskey bin]# [ -z $a ] && echo yes || echo noyes[root@Miskey bin]# [ -n $a ] && echo yes || echo noyes[root@Miskey bin]# [ -n "$a" ] && echo yes || echo nono[root@Miskey bin]# [ -z "$a" ] && echo yes || echo noyes[root@Miskey bin]# [[ -n $a ]] && echo yes || echo nono[root@Miskey bin]# [[ -z $a ]] && echo yes || echo noyes#============================================================================[root@Miskey ~]# name=haha[root@Miskey ~]# echo $namehaha[root@Miskey ~]# [[ "$name" =~ ha ]][root@Miskey ~]# echo $?0[root@Miskey ~]# [[ "$name" =~ h ]][root@Miskey ~]# echo $?0[root@Miskey ~]# [[ "$name" =~ hx ]][root@Miskey ~]# echo $?1[root@Miskey ~]# [[ "$name" =~ xx ]][root@Miskey ~]# echo $?1 |
3.文件测试
★存在性测试
-a FILE:同-e
-e FILE:文件存在性测试,存在为真,否则为假;
★存在性及类型测试
-b FILE:是否存在且为块设备文件;
-c FILE:是否存在且为字符设备文件;
-d FILE:是否存在且为目录文件;
-f FILE:是否存在且为普通文件;
-h FILE 或-L FILE:存在且为符号链接文件;
-p FILE:是否存在且为命名管道文件;
-S FILE:是否存在且为套接字文件;
★文件权限测试
-r FILE:是否存在且对当前用户可读;
-w FILE:是否存在且对当前用户可写;
-x FILE:是否存在且对当前用户可执行
★文件特殊权限测试
-g FILE:是否存在且拥有sgid权限;
-u FILE:是否存在且拥有suid权限;
-k FILE:是否存在且拥有sticky权限;
★文件是否有内容
-s FILE:是否存在且非空(即,文件是否有内容);
★文件时间戳测试
-N FILE:文件自从上一次读操作后是否被修改过;
★从属关系测试
-O FILE:当前用户是否为文件的属主;
-G FILE:当前用户是否属于文件的属组;
★文件是否打开
-t fd:fd表示文件描述符是否已经打开且与某终端相关;
★双目测试
FILE1 -ef FILE2:FILE1与FILE2是否指向同一个设备上的相同inode;
FILE1 -nt FILE2:FILE1是否新于FILE2;(修改时间)
FILE1 -ot FILE2:FILE1是否旧于FILE2;
注意:
文件测试一般使用 [ ] 就可以
演示:
1.文件存在性测试
|
1
2
3
4
5
6
|
[root@Miskey ~]# [ -e /etc/fstab ][root@Miskey ~]# echo $?0[root@Miskey ~]# [ -e /etc/rc.d/rc.sysinit ][root@Miskey ~]# echo $?1 |
2.文件存在性及类型测试
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
[root@Miskey ~]# [ -b /dev/sda ][root@Miskey ~]# echo $?0[root@Miskey ~]# [ -b /dev/sdb ][root@Miskey ~]# echo $?1[root@Miskey ~]# [ -d /etc ][root@Miskey ~]# echo $?0[root@Miskey ~]# [ -L /etc/redhat-release ][root@Miskey ~]# echo $?0[root@Miskey ~]# ll /etc/redhat-release lrwxrwxrwx. 1 root root 14 11月 6 18:30 /etc/redhat-release -> centos-release |
3.文件权限及特殊权限测试
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
|
[root@Miskey ~]# ll /etc/shadow---------- 1 root root 1400 2月 20 14:12 /etc/shadow[centos@Miskey ~]$ whoamicentos[centos@Miskey ~]$ [ -r /etc/shadow ][centos@Miskey ~]$ echo $?1[centos@Miskey ~]$ [ -r /etc/passwd ][centos@Miskey ~]$ echo $?0[centos@Miskey ~]$ [ -w /etc/passwd ][centos@Miskey ~]$ echo $?1# 对于root用户来讲,rw 权限是以实际为主,但执行权限是起作用的[root@Miskey ~]# whoamiroot[root@Miskey ~]# [ -r /etc/shadow ][root@Miskey ~]# echo $?0[root@Miskey ~]# [ -w /etc/shadow ][root@Miskey ~]# echo $?0[root@Miskey ~]# [ -x /etc/shadow ][root@Miskey ~]# echo $?1#==========================================================================[root@Miskey ~]# [ -u /usr/bin/passwd ][root@Miskey ~]# echo $?0 # 说明 /usr/bin/passwd 拥有suid权限[root@Miskey ~]# ll /usr/bin/passwd -rwsr-xr-x. 1 root root 27832 6月 10 2014 /usr/bin/passwd |
4.文件是否有内容测试
|
1
2
3
4
5
6
7
8
|
[root@Miskey ~]# touch /tmp/hello[root@Miskey ~]# [ -s /tmp/hello ][root@Miskey ~]# echo $?1[root@Miskey ~]# [ -s /etc/fstab ][root@Miskey ~]# echo $?0 |
5.双目测试
|
1
2
3
4
5
6
7
8
9
10
|
[root@Miskey ~]# touch f1[root@Miskey ~]# ln f1 f22 # 创建f22 的硬链接为f1[root@Miskey ~]# [ f1 -ef f22 ] # 是否指向同一设备上相同的inode,也就是说是否为硬链接[root@Miskey ~]# echo $?0[root@Miskey ~]# ll -i f1 f22201391291 -rw-r--r-- 2 root root 1024 2月 23 18:39 f1201391291 -rw-r--r-- 2 root root 1024 2月 23 18:39 f22 |
4.组合测试条件
★第一种方式:逻辑判断符
OMMAND1 && COMMAND2 :并且;
COMMAND1 || COMMAND2 :或者;
!COMMAND :非
示例:
[ -O FILE ] && [ -r FILE ]
★第二种方式:布尔运算符
EXPRESSION1 -a EXPRESSION2 :并且
EXPRESSION1 -o EXPRESSION2 :或者
! EXPRESSION:取反
注意:
布尔运算符(-a ,-o, !)只能用在 [ ] 表达式中;如:[ 1 -eq 1 -a 2 -eq 2 ]为true;[ 1 -eq 1 -o 2 -eq 1 ]为true
逻辑运算符(&&, ||)只能用在 ` `和(( ))中使用
总结:
1.条件表达式
|
表达式 |
示例 |
| [ expression ] | [ 1 -eq 1 ] |
| ` expression ` | ` 1 -eq 1 ` |
| test expression | test 1 -eq 1 ,等同于[] |
2.整数比较符
|
比较符 |
描述 |
示例 |
| -eq,equal | 等于 | [ 1 -eq 1 ]为true |
| -ne,not equal | 不等于 | [ 1 -ne 1 ]为false |
| -gt,greater than | 大于 | [ 2 -gt 1 ]为true |
| -lt,lesser than | 小于 | [ 2 -lt 1 ]为false |
| -ge,greater or equal | 大于或等于 | [ 2 -gt 1 ]为true |
| -le,lesser or equal | 小于或等于 | [ 2 -le 1 ]为false |
3.字符串比较符
|
运算符 |
描述 |
示例 |
| == | 等于 | [ "a" == "a" ]为true |
| != | 不等于 | [ "a" != "a" ]为false |
| > | 大于,判断字符串时根据ASCII码表顺序,不常用 |
在[]表达式中:[ 2 \> 1 ]为true 在[[]]表达式中:[[ 2 > 1 ]]为true 在(())表达式中:(( 3 > 2 ))为true |
| < | 小于,判断字符串时根据ASCII码表顺序,不常用 |
在[]表达式中:[ 2 \< 1 ]为false 在[[]]表达式中:[[ 2 < 1 ]]为false 在(())表达式中:(( 3 < 2 ))为false |
| >= | 大于等于 | 在(())表达式中:(( 3 >= 2 ))为true |
| <= | 小于等于 | 在(())表达式中:(( 3 <= 2 ))为false |
| -n | 字符串长度不等于0为真 |
VAR1=1;VAR2="" [ -n "$VAR1" ]为true [ -n "$VAR2" ]为false |
| -z | 字符串长度等于0为真 |
VAR1=1;VAR2="" [ -z "$VAR1" ]为false [ -z "$VAR2" ]为true |
| str | 字符串存在为真 |
VAR1=1;VAR2="" [ $VAR1 ]为true [ $VAR2 ]为false |
4.文件测试
|
测试符 |
描述 |
示例 |
| -e | 文件或目录存在为真 | [ -e path ] path存在为true |
| -f | 文件存在为真 | [ -f file_path ] 文件存在为true |
| -d | 目录存在为真 | [ -d dir_path ] 目录存在为true |
| -r | 有读权限为真 | [ -r file_path ] file_path有读权限为true |
| -w | 有写权限为真 | [ -w file_path ] file_path有写权限为true |
| -x | 有执行权限为真 | [ -x file_path ] file_path有执行权限为true |
| -s | 文件存在并且大小大于0为真 | [ -s file_path ] file_path存在并且大小大于0为true |
5.布尔运算符
|
运算符 |
描述 |
示例 |
| ! | 非关系,条件结果取反 | [ ! 1 -eq 2 ]为true |
| -a | 和关系,在[]表达式中使用 | [ 1 -eq 1 -a 2 -eq 2 ]为true |
| -o | 或关系,在[]表达式中使用 | [ 1 -eq 1 -o 2 -eq 1 ]为true |
6.逻辑判断符
|
判断符 |
描述 |
示例 |
| && | 逻辑与,在` `和(( ))表达式中或判断表达式是否为真时使用 |
[[ 1 -eq 1 && 2 -eq 2 ]]为true (( 1 == 1 && 2 == 2 ))为true [ 1 -eq 1 ] && echo yes 表示:如果&&前面表达式为true则执行后面的 |
| || | 逻辑或,在` `和(( ))表达式中或判断表达式是否为真时使用 |
[[ 1 -eq 1 || 2 -eq 1 ]]为true (( 1 == 1 || 2 == 2 ))为true [ 1 -eq 2 ] || echo yes 表示:如果||前面表达式为false则执行后面的 |
7.整数运算
|
运算符 |
描述 |
| + | 加法 |
| - | 减法 |
| * | 乘法 |
| / | 除法 |
| % | 取余 |
|
运算表达式 |
示例 |
| $(()) | $((1+1)) |
| $[] | $[1+1] |
除了Shell本身的算数运算表达式,还有几个命令支持复杂的算数运算:
|
命令 |
描述 |
示例 |
| let | 赋值并运算,支持++、-- |
let VAR=(1+2)*3 ; echo $VAR x=10 ; y=5 let x++;echo $x 每执行一次x加1 let y--;echo $y 每执行一次y减1 let x+=2 每执行一次x加2 let x-=2 每执行一次x减2 |
| expr | 乘法*需要加反斜杠转义\* |
expr 1 \* 2 运算符两边必须有空格 expr \( 1 + 2 \) \* 2 使用双括号时要转义 |
| bc | 计算器,支持浮点运算、平方等 |
bc本身就是一个计算器,可直接输入命令,进入解释器。 echo 1 + 2 |bc 将管道符前面标准输出作为bc的标准输入 echo "1.2+2" |bc echo "10^10" |bc echo 'scale=2;10/3' |bc 用scale保留两位小数点
|
看到这里,想一想里面所讲的小括号、中括号的用途,是不是有点懵逼了。那我们总结一下!
| ( ) |
用途1:在运算中,先计算小括号里面的内容 用途2:数组 用途3:匹配分组 |
| (( )) |
用途1:表达式,不支持-eq这类的运算符。不支持-a和-o,支持<=、>=、<、>这类比较符和&&、|| 用途2:C语言风格的for(())表达式 |
| $( ) | 执行Shell命令,与反撇号等效 |
| $(( )) |
用途1:简单算数运算 用途2:支持三目运算符 $(( 表达式?数字:数字 )) |
| [ ] | 条件表达式,里面不支持逻辑判断符(&&,|| ) |
| ` ` | 条件表达式,里面不支持-a和-o,不支持<=和>=比较符,支持-eq、<、>这类比较符。支持=~模式匹配,也可以不用双引号也不会影响原意,比[]更加通用 |
| $[ ] | 简单算数运算 |
| { } | 对逗号(,)和点点(...)起作用,比如touch {1,2}创建1和2文件,touch {1..3}创建1、2和3文件 |
| ${ } |
用途1:引用变量 用途2:字符串处理 |
练习:
1、编写脚本/root/bin/systeminfo.sh,显示当前主机系统信息,包括主机名,IPv4地址,操作系统版本,内核版本,CPU型号,内存大小,硬盘大小。
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
[root@Miskey bin]# cat systeminfo.sh #!/bin/bash# 取 IP 地址,采用sed方法,掐头去尾server_ip=$(ifconfig |sed -n '2p' |sed -e 's@^.*inet@@' -e 's@net.*@@')CPUmod=$(lscpu | grep -i "model name:")Meninfo=$(free -h | sed -n '2p' | tr -s ' ' | cut -d' ' -f2)DISKinfo=$(fdisk -l |grep "Disk /dev/[sh]d[a-z]" |sed -r 's@.* ([0-9]+.*GB).*@\1@')echo 'hostname :'$(hostname)echo 'hostIP:'$server_ipecho 'OS version:'$(cat /etc/redhat-release)echo 'Kernel version:'$(uname -r)echo 'CPU '$CPUmodecho 'Memory :'$Meninfoecho 'Harddisk:'$DISKinfo# 执行脚本[root@Miskey bin]# chmod +x systeminfo.sh[root@Miskey bin]# ll systeminfo.sh-rwxr-xr-x 1 root root 522 Feb 23 21:42 systeminfo.sh[root@Miskey bin]# cd[root@Miskey ~]# systeminfo.shhostname :MiskeyhostIP: 10.0.0.19OS version:CentOS Linux release 7.2.1511 (Core)Kernel version:3.10.0-327.el7.x86_64CPU Model name: Intel(R) Core(TM) i3-2328M CPU @ 2.20GHzMemory :977MHarddisk:99.9 GB |

浙公网安备 33010602011771号