Shell编程学习之二
一、bash的条件测试
测试方法或者说测试书写:
test EXPR
[ EXPR ]
` EXPR `
例如:测试变量 User_Name 的之是否为root
test $User_Name="root"
[ $User_Name == "root" ]
[[ $User_Name == "root" ]
根据比较时操作数的类型,测试类型分为:
测试类型 | 运算符 | 运算符所代表的意义 | 示例 |
整形测试 | -gt -lt -ge -le -eq -ne |
-gt 大于 -lt 小于 -ge 大于或等于 -le 小于或等于 -eq 等于 -ne 不等于 |
都是双目运算符: [ $num -gt 3 ] test $num -ne $sum [[ $num -ne 0 ]] |
字符测试 | == =~ > < != | == 等于 >大于 < 小于 != 不等于 =~ 模式匹配 |
都是双目运算符: [ $num == "root"] test $num > $sum [[ "$num" =~ /bin/bash$ ]] 这里注意 =~只能用 ` `去匹配,而且=~后面的PATTERN(模式)不能使用"",''等引用字符 |
-n -z | -z 测试文件内容是否为空,为空时真,不为空为假 -n 测试文件内容是否为不空,不空为真,空为假 |
单目运算符 [ -n "$file_name" ] |
|
文件测试 | -a|e -f -L|h -d -b -c -S -p -s -r -w -x -N |
-a|e 测试文件存在 -f 测试文件为一般文件 -L|h 测试文件为软连接文件 -d 测试文件是否为目录 -b -c -p -S 测试文件为块设备、字符设备、管道文件、socket文件 -r -w -x 测试文件可读、可写、可执行 -s 测试文件为空文件 -N 测试文件Mtime新于Atime |
都是单目运算符 [ -f "$file_name" ] [[ -b "$file_name" ]] test -x $file_name |
-nt -ot | file1 -nt file2 file1的Mtime新于file2的Mtime file1 -ot file2 file1的Mtime旧于file2的Mtime |
双目运算符 [ file1 -nt "$file_name" ] [[ $file1 -ot "$file_name" ]] |
二、逻辑运算
布尔运算:布尔运算的结果只有2中:真和假。
常见的逻辑运算有:与 或 非 异或。与或非常用 && || ! 来表示。
与的逻辑关系:
假 && 任意 | 假 |
真 && 真 | 真 |
或的逻辑关系:
真 || 任意 | 真 |
假 || 假 | 假 |
非的逻辑关系:
!假 | 真 |
!真 | 假 |
异或的逻辑关系:相同为假,不同为真
三、选择
bash中的选择语句通常有if,case。当然if,case在大多数情况下是可以相互转换的。
1)if选择语句
1、单分支if语句:
if CONDITION;then
选择分支
fi
2、双分支的if语句:
if CONDITION;then
选择分支1
else
选择分支2
fi
3、多分支的if语句:
if CONDITION1;then
选择分支1
elif CONDITION2;then
选择分支2
elif CONDITION3;then
选择分支3
...
else
选择分支n
fi
2)case语句
语法格式:
case 变量引用 in
PATTERN1)
分支1
;;
PATTERN2)
分支2
;;
...
*)
分支n
;;
esac
PATTERN:类同于文件名通配机制,但支持使用“|”表示或者
a|b: a或者b
*:匹配任意长度的任意字符
?: 匹配任意单个字符
[]: 指定范围内的任意单个字符
4、练习
写一个脚本,完成如下任务,其使用形式如下所示:
script.sh {start|stop|restart|status}
其中:
如果参数为空,则显示帮助信息,并退出脚本;
如果参数为start,则创建空文件/var/lock/subsys/script,并显示“starting script successfully.”
如果参数为stop,则删除文件/var/lock/subsys/script,并显示“Stop script successfully.”
如果参数为restart,则删除文件/var/locksubsys/script并重新创建,而后显示“Restarting script successfully.”
如果参数为status,那么:
如果文件/var/lock/subsys/script存在,则显示“Script is running...”,否则,则显示“Script is stopped.”
说明:script.sh是脚本文件名,在创建时,其名称可以自己随意定义,但如果其名称发生变量,上/var/lock/sussys/下的文件名也要随之而变;
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
|
[root@server scripts]
# cat myhttpd
#!/bin/bash
#
# Description:
# Version: 0.0.1
# Author: Alex
# Date: 2014-07-09
#判断参数个数,如果参数小于1,则提示用法并退出
if
[ $
# -lt 1 ];then
echo
"Usage: `basename $0` {start|stop|restart|status}"
exit
2
fi
#判断/var/lock/subsys是否存在,不存在则创建此目录
if
[ ! -d
/var/lock/subsys
];
then
/bin/mkdir
-p
/var/lock/subsys
fi
if
[
"$1"
==
"start"
];
then
#如果/var/lock/subsys/`basename $0`文件不存在,则创建,并显示启动成功;若存在则提示已启动
[ ! -e
"/var/lock/subsys/`basename $0`"
] &&
/bin/touch
"/var/lock/subsys/`basename $0`"
&&
echo
"Starting `basename $0` successfully."
\
||
echo
"`basename $0` is already start."
elif
[
"$1"
==
"stop"
];
then
#如果/var/lock/subsys/`basename $0`文件存在,则删除,并显示关闭成功;若不存在则显示关闭失败
[ -e
"/var/lock/subsys/`basename $0`"
] &&
/bin/rm
-f
"/var/lock/subsys/`basename $0`"
&&
echo
"Stop myhttpd successfully."
\
||
echo
-e
"Stopping myhttpd \033[31mFAILED\033[0m."
elif
[
"$1"
==
"status"
];
then
#如果/var/lock/subsys/`basename $0`文件存在,显示running;若不存在则提示stopd
[ -e
"/var/lock/subsys/`basename $0`"
] &&
echo
"`basename $0` is running..."
||
echo
"`basename $0` is stopped."
else
echo
"Usage: `basename $0` {start|stop|restart|status}"
fi
|
上面的脚本也可以用case语句结合函数来实现。
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
|
# 一般情况下,case与函数一起使用的居多。
#!/bin/bash
if
[ $
# -lt 1 ];then
echo
"Usage: `basename $0` {start|stop|restart|status}"
exit
2
fi
[ $UID -
ne
0 ] &&
echo
"permission denied."
&&
exit
5
if
[ ! -d
/var/lock/subsys
];
then
/bin/mkdir
-p
/var/lock/subsys
fi
service_name=`
basename
$0`
ser_path=
"/var/lock/subsys/$service_name"
start() {
if
[ ! -e
"$ser_path"
];
then
/bin/touch
"$ser_path"
echo
"Starting $service_name successfully."
else
echo
"$service_name is already start."
fi
}
stop() {
if
[ -e
"$ser_path"
];
then
/bin/rm
-f
"$ser_path"
echo
"Stop $service_name successfully."
else
echo
-e
"Stopping $service_name \033[31mFAILED\033[0m."
fi
}
status() {
if
[ -e
"$ser_path"
];
then
echo
"$service_name is running..."
else
echo
"$service_name is stopped."
fi
}
other() {
echo
"Usage: $service_name {start|stop|restart|status}"
exit
4
}
case
"$1"
in
start)
start
;;
stop)
stop
;;
status)
status
;;
*)
other
;;
esac
|
四、其他
1、组合条件测试:在多个条件间实现逻辑运算
与:[ condition1 -a condition2 ]
condition1 && condition2
或:[ condition1 -o condition2 ]
condition1 || condition2
非:[ -not condition ]
! condition
2、bash编程之交互编程
read 与用户交互进行
-p "prompt" 提示语句
-t timeout 设置超时时间
3、exit
程序退出语句,一般是 exit n 这样使用,n是错误状态值。
4、shift
通常是shift n 这样使用,n是要踢掉的参数个数
1
2
3
4
5
6
7
8
9
10
11
12
|
[root@server scripts]
# cat ./aboutshift
#!/bin/bash
echo
$1
shift
2
#踢掉2个参数
echo
$1
shift
3
#踢掉3个参数
echo
$1
[root@server scripts]
# ./aboutshift 1 2 3 4 5 6 7 8 9 10
1
3
6
|
而shift真正的作用是,判断脚本参数的问题。例如:
写一个脚本,使用形式如下所示
showifinfo.sh [-i INTERFACE|-a] [-v]
要求:
1、-i或-a不可同时使用,-i用于指定特定网卡接口,-a用于指定所有接口;
显示接口的ip地址
2、使用-v,则表示显示详细信息
显示接口的ip地址、子网掩码、广播地址;
3、默认表示仅使用-a选项;
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
|
#!/bin/bash
#
# 通过这种方法来判断一个脚本的参数选项
verbose=0
allInterface=0
ifflag=0
while
[ $
# -ge 1 ]; do
case
$1
in
-a)
allInterface=1
shift
1
;;
-i)
ifflag=1
interface=
"$2"
shift
2
;;
-
v
)
verbose=1
shift
;;
*)
echo
"wrong option"
exit
2
;;
esac
done
[ $ifflag -
eq
1 -a $allInterface -
eq
1 ] &&
"Usage Error."
&&
exit
12
if
[ $allInterface -
eq
1 || $
# -eq 0 ]; then
if
[ $verbose -
eq
1 ];
then
ifconfig
|
grep
"inet addr:"
else
ifconfig
|
grep
"inet addr:"
|
awk
'{print $2}'
fi
fi
if
[ $ifflag -
eq
1 ];
then
if
[ $verbose -
eq
1 ];
then
ifconfig
$interface |
grep
"inet addr:"
else
ifconfig
$interface |
grep
"inet addr:"
|
awk
'{print $2}'
fi
fi
|