主要从事Linux,云原生架构改造,服务网格,ELK,python,golang等相关技术。
分类: LINUX
2015-05-09 14:20:15
1.变量的处理计算变量长度与其他不同方法的耗时对比
[root@server2 ~]# chars=`seq -s "" 100`2015-1-22
[root@server2 ~]# echo ${#chars}
291
[root@server2 ~]# echo $(expr length "$chars")
291
[root@server2 ~]# echo ${chars} | wc -m
292
[root@server2 ~]# time for i in $(seq 11111);do count=${#chars};done;
real 0m2.446s
user 0m2.415s
sys
0m0.028s
[root@server2 ~]# time for i in $(seq 11111);do count=${chars} | wc -m ;done;
real 1m0.134s
user 0m13.734s
sys
0m23.029s
[root@server2 ~]# time for i in $(seq 11111);do count=`echo expr length "${chars}"`;done;
real 0m18.653s
user 0m7.708s
sys
0m8.562s
我们看到速度相差几十到上百倍,一般情况调用外部命令处理,与内置功能操作性能相差较
大。在 shell 编程中我们应尽量使用内置操作或函数完成。
变量处理替换的一些参考资料
01)man bash 变量处理大全
02)http://www.cnblogs.com/chengmo/archive/2010/10/02/1841355.html
[root@server2 ~]# man bash 进入后查找 word,我们一直往下翻就可以看到对字符的各种处
理
注:我们要想成为比较好的,我们就要看官方的一首资料,但是如果实在不行,我们可以去
网上搜集二手的资料,比如别人总结好的资料
2.变量的数值计算
变量的数值计算常见的有如下几种命令:
(())、let、expr、bc $[]
1) (())用法:(此法很常用,且效率高)
用于执行简单的整数运算,只需将特定的算术表达式用"$(("和"))"括起来
shell 的算术运算符号都置于"$(("..."))"的语法中。这一语法如同双引号功能,除了内嵌双引号
无需转义。
范例 1:shell 的算术运算实例如下:
[root@server2 ~]# ((a=1+2**3-4%3))
[root@server2 ~]# echo $a
8
[root@server2 ~]# b=$((1+2**3-4%3))
//两个**为幂运算
[root@server2 ~]# echo $b
8
[root@server2 ~]# echo $((1+2**3-4%3))
8
[root@server2 ~]# echo $((a+=1))
9
[root@server2 ~]# echo $((a++))
9
[root@server2 ~]# echo $a
10
[root@server2 ~]# echo $((a--))
10
[root@server2 ~]# echo $a
9
[root@server2 ~]# echo $((--a))
8
[root@server2 ~]# echo $((3>2))
1
[root@server2 ~]# echo $((3<2))
0
[root@server2 ~]# echo $((100*(100+1)/2))
5050
注意:
a.上面涉及到的变量必须是整数,不能是小数或者是字符串。
b.bc 命令可以进行浮点数运算,但一般较少用到,下面会讲到。提示:你可以直接在
shell 脚本中使用上述命令进行计算。
范例 3:
[root@server2 ~]# myvar=99
[root@server2 ~]# echo $(($myvar + 1))
100
[root@server2 ~]# echo $(( $myvar + 1 ))
//(()
)两边有几个空格不敏感,也可以没有
100
[root@server2 ~]# myvar=$(( $myvar + 1))
//还可以赋值给变量然后输出变量
[root@server2 ~]# echo $myvar
100
范例 4:各种(())的计算命令行执行例子
[root@server2 ~]# echo $(( 100/5 ))
20
[root@server2 ~]# echo $(( 100 + 5 ))
105
[root@server2 ~]# echo $(( 100 - 5 ))
95
[root@server2 ~]# echo $(( 100 * 5 ))
500
[root@server2 ~]# echo $(( 100 ** 5 ))
//幂
10000000000
[root@server2 ~]# echo $(( 100 %5 ))
0
范例 5:各种(())运算的 shell 脚本例子
[root@server2 ~]#cat test.sh
#!/bin/bash
a=6
b=2
echo "a-b=$(( $a - $b ))"
echo "a+b=$(( $a + $b ))"
echo "a*b=$(( $a * $b ))"
echo "a/b=$(( $a / $b ))"
echo "a**b=$(( $a ** $b ))"
echo "a%b=$(( $a %$b ))"
[root@server2 ~]#sh test.sh
a-b=4
a+b=8
a*b=12
a/b=3
a%b=0
[root@server2 ~]#cat test.sh
#!/bin/bash
a=$1
b=$2
echo "a-b=$(( $a - $b ))"
echo "a+b=$(( $a + $b ))"
echo "a*b=$(( $a * $b ))"
echo "a/b=$(( $a / $b ))"
echo "a**b=$(( $a ** $b ))"
echo "a%b=$(( $a %$b ))"
[root@server2 ~]#sh test.sh 6 2
a-b=4
a+b=8
a*b=12
a/b=3
a**b=36
a%b=0
[root@server2 ~]#cat jisuan.sh
//一个四则运算器
#!/bin/bash
#add,subtract,multiply and divide by yubing 2013-07-13
print_usage(){
printf "Please enter an integer \n"
}
for i in $(seq 100)
{
read -p "Please input first number:" firstnum
if [ -n "`echo $firstnum | sed 's/[0-9]//g'|sed 's/-//g'`" ];then
print_usage;
continue;
fi
break;
}
for i in $(seq 100)
{
read -p "Please input the opertors:" operators
if [ "${operators}" != "+" ]&&[ "${operators}" != "*" ]&&[ "${operators}" != "/" ];then
echo "please use + - * /"
continue;
fi
break;[root@server2 ~]# sh jisuan.sh
Please input first number:3
Please input the opertors:*
Please input second number:2
3*2=6
网友的例子:
http://zhangbo.blog.51cto.com/350645/1172900
http://blog.163.com/shaohj_1999@126/blog/static/634068512011388619129/
2)let 命令的用法
格式:
let 赋值表达式
注:let 赋值表达式功能等同于:(
(赋值表达式))
范例 1:给自变量 i 加 8
[root@server2 ~]# i=2
[root@server2 ~]# let i=i+8
[root@server2 ~]# echo $i
10
[root@server2 ~]# i=i+8
//去掉 let 定义
[root@server2 ~]# echo $i
i+8
输出的结果
提示:let i=i+8 等同于((i=i+8)
),但后者效率更高
范例 2:利用 let 计数监控 web 服务状态
#监控服务状态
ServerMonitor(){
#服务状态监控
timeout=10
fails=0
success=0
while true
do
/usr/bin/wget --timeout=$timeout --tries=1 http://192.168.2.2/ -q -o /dev/null
if [ $? -ne 0 ]
then
let fails=fails+1
success=0
else
fails=0
let success=1
fi
if [ $success -ge 1 ]
then
exit 0;
fi
if [ $fails -ge 2 ]
then
Critical=”TMS 应用服务出现故障,紧急处理!”
echo $Critical | mutt -s “服务 down” yhai_ying@163.com
exit
fi
done
}
3)expr (evaluate expressions)命令的用法:
expr 命令一般用于整数值,但也可用于字符串,用来求表达式变量的值,同时 expr
也是一个手工命令行计算器
语法:expr Expression
[root@server2 ~]# expr 2+2
2+2
[root@server2 ~]# expr 2 + 2
4
[root@server2 ~]# expr 2 - 2
0
[root@server2 ~]# expr 2 * 2
expr: 语法错误
[root@server2 ~]# expr 2 \* 2
//其中*号用/来转义
4
[root@server2 ~]# echo $(expr length "we are hy.")
10
提示:
1)注意运算符左右都有空格
2)使用乘号时,反斜线屏蔽其特定含义。因为 shell 可能会误解星号的含义
增量计算
Expr 在循环中可用于增量计算。首先,循环初始化为 0,然后循环值加 1,反引号
的用法为命令替代。最基本的一种是从(expr)命令接受输出并将之放入循环变量。
例:给自变量 i 加 1
[root@server2 ~]# i=0
[root@server2 ~]# i=`expr $i + 1`
//这样计算的效率很低
[root@server2 ~]# echo $i
1
expr $[$a+$b]表达式形式,其中$a$b 可为整数值
[root@server2 ~]# expr $[2+3]
5
[root@server2 ~]# expr $[2*3]
6
[root@server2 ~]# expr $[2**3]
8
[root@server2 ~]# expr $[2/3]
0
[root@server2 ~]# expr $[2%3]
2
[root@server2 ~]# a=5
[root@server2 ~]# b=6
[root@server2 ~]# expr $[$a+$b]
11
expr 将其后的串解释为表达式并计算其值,运算符前后需有空格
其他特殊用法:
expr 用法 ssh-copy-id 脚本
[root@hy ~]# vim /usr/bin/ssh-copy-id
ID_FILE="${HOME}/.ssh/id_rsa.pub"
if [ "-i" = "$1" ]; then
shift
# check if we have 2 parameters left, if so the first is the new ID
file
if [ -n "$2" ]; then
if expr "$1" : ".*\.pub" > /dev/null ; then
ID_FILE="$1"
else
ID_FILE="$1.pub"
fi
shift
# and this should leave $1 as the target name
其中:expr "$1" : ".*\.pub" 匹配*.pub 格式的文件如果是则为真非零,如果为假则
输出 0
[root@server2 ~]# expr "test.txt" : ".*\.pub"
0
[root@server2 ~]# expr "test.pub" : ".*\.pub"
8
这里显示的是 test.pub 这个字符串的长度
判断文件或字符串的扩展名小案例:
[root@server2 ~]# expr "test.txt" : ".*\.pub" && echo 1 || echo 0
0
0
[root@server2 ~]# expr "test.pub" : ".*\.pub" && echo 1 || echo 0
8
1
通过 expr 判断变量是否为整数
[root@server2 ~]# vim expr.sh
#!/bin/bash
while true
do
read -p "Pls input:" a
expr $a + 0 &>/dev/null
//expr $a + 0 >/dev/null 2>&1
[ $? -eq 0 ] && echo int || echo chars
done
[root@server2 ~]# sh expr.sh
Pls input:a
chars
Pls input:8.21
chars
Pls input:2
Int
通过 expr 计算字符串的长度
[root@server2 ~]# chars=`seq -s "" 100`
[root@server2 ~]# echo ${#chars}
291
[root@server2 ~]# echo $(expr length "$chars")
291
4)bc 命令的用法:
bc 是 UNIX 下的计算器,它也可以用在命令行下面:
例:
[root@server2 ~]# i=2
[root@server2 ~]# echo $i+1
2+1
[root@server2 ~]# echo $i+1 | bc
3
//可以计算,但是效率比较低
*因为 bc 支持科学计算,所以这种方法功能非常强大
[root@server2 ~]# echo 3.5+5 |bc
8.5
[root@server2 ~]# echo 3.5+5.6 |bc
9.1
[root@server2 ~]# echo 3.5-3.1 |bc
.4
通过计算表达式计算
[root@server2 ~]# seq -s "+" 10
1+2+3+4+5+6+7+8+9+10
[root@server2 ~]# seq -s "+" 10 |bc
55
[root@server2 ~]# echo "scale=2;5.23 / 3.13" |bc
//这样表示保留两位小数
1.67
[root@server2 ~]# echo "obase=2;8"|bc
//这样表示进制转换
1000
[root@server2 ~]# echo "obase=16;32" |bc
20
特点:bc 的特点是支持小数运算
5)typeset 命令的用法:
[root@server2 ~]# typeset -i A=1 B=3
[root@server2 ~]# A=A+B
//效率高
[root@server2 ~]# echo $A
4
6)$[]的用法:
[root@server2 ~]# echo $[2+3]
5
[root@server2 ~]# echo $[ 2 + 3 ]
5
[root@server2 ~]# echo $[2-3]
-1
[root@server2 ~]# echo $[2*3]
6
[root@server2 ~]# echo $[2/3]
0
[root@server2 ~]# echo $[2%3]
2
实际解决问题例子:打印数学杨辉三角(第一种为重点)
http://oldboy.blog.51cto.com/2561410/756234
#!/bin/bash
if(test -z $1);then
======================================================================
3.shell 变量的输入
Shell 变量除了可以直接赋值或脚本传参外,还可以使用 read 命令从标准输入获得
『语法格式』
read 『参数』『变量名』
『常用参数』
-p prompt:设置提示信息
-t timeout:设置输入等待的时间,单位默认为秒。
范例 1:read 的基本读入
[root@server2 ~]# read -p "please input a number:" a //指定提示符
please input a number:3
[root@server2 ~]# read -t 3 -p "please input a number:" a //指定自动退出时间
please input a number:[root@server2 ~]#
[root@server2 ~]# read -t 5 -p "please input a number:" a b
//可连续接收多个值
please input a number:33 44
[root@server2 ~]# echo $a $b
33 44
提示:上面 read -p 的功能可以用 echo 和 read 实现
echo -n “please input two number:”
read a1 a2
以上两句和下面的命令相当(-t 排除在外)
例:实现简单的计算器功能
read.sh
#!/bin/bash
#read -p "please input two numbers:" a b
echo -n "please input two numbers:"
read a b
echo "a+b = $(( $a + $b ))"
echo "a-b = $(( $a - $b ))"
echo "a*b = $(( $a * $b ))"
echo "a/b = $(( $a / $b ))"
echo "a**b = $(( $a ** $b ))"
echo "a%b = $(( $a %$b ))"
如何用循环判断输入的数不是整数,并且重新输入:
方法一:
#!/bin/bash
$a
$b
function_input(){
read -p "Pls input:" c
for i in $(seq 10)
do
expr $c + 0 &>/dev/null
[ $? -eq 0 ] && break || read -p "please reinput:" c
done
}
function_input;
a=$c
function_input;
b=$c
echo "a+b = $(( $a + $b ))"
echo "a-b = $(( $a - $b ))"
echo "a*b = $(( $a * $b ))"
echo "a/b = $(( $a / $b ))"
echo "a**b = $(( $a ** $b ))"
echo "a%b = $(( $a %$b ))"
方法二:
#!/bin/bash
$a
$b
function_input(){
read -p "Pls input:" c
while true
do
expr $c + 0 &>/dev/null
[ $? -eq 0 ] && break || read -p "please reinput:" c
done
}
function_input;
a=$c
function_input;
b=$c
echo "a+b = $(( $a + $b ))"
echo "a-b = $(( $a - $b ))"
echo "a*b = $(( $a * $b ))"
echo "a/b = $(( $a / $b ))"
echo "a**b = $(( $a ** $b ))"
echo "a%b = $(( $a %$b ))"
======================================================================
4.条件测试
1)测试语句
1.1)条件测试语法
在 bash 的各种流程控制结构中通常要进行各种测试,然后根据测试结果执行不同
的操作,有时也会通过与 if 等条件语句相结合,让我们可以方便的完成判断。
生活中的例子:我要去图书馆,问一下
『语法说明』
格式 1:test<测试表达式>
格式 2:[<测试表达式>]
格式 3:[[<测试表达式>]]
说明:
格式 1 和格式 2 是等价的。
格式 3 为扩展的 test 命令,有网友推荐用格式 3,老男孩习惯用格式 2.
提示:
在[[]]中可以使用通配符。&&、||、>、<等操作符可以应用于[[]]中,但不能应用于
[]中。
对整数进行关系运算,也可以使用 shell 的算术运算符(()).
『语法例子』
格式 1: test<测试表达式>
范例 1:test 测试文件
[root@server2 ~]# test -f file && echo true || echo false
false
[root@server2 ~]# touch file
[root@server2 ~]# test -f file && echo true || echo false
true
范例 2:test 命令非(!)的写法
[root@server2 ~]# test ! -f file && echo true || echo false
true
[root@server2 ~]# touch file
[root@server2 ~]# test ! -f file && echo true || echo false
false
格式 2:[<测试表达式>]
范例:[]
[root@server2 ~]# rm -f file
[root@server2 ~]# [ -f file ] && echo true|| echo false
false
[root@server2 ~]# touch file
[root@server2 ~]# [ -f file ] && echo true|| echo false
true
[root@server2 ~]# [ -f file ] && cat file
[root@server2 ~]# vim file
[root@server2 ~]# [ -f file ] && cat file
hello
格式 3:[[<测试表达式>]]
范例:[[]]
[root@server2 ~]# [[ -f file && -d dir ]] && echo 1 || echo 0
0
[root@server2 ~]# [ -f file && -d dir ] && echo 1 || echo 0
-bash: [: missing `]'
0
[root@server2 ~]# [ -f file -a -d dir ] && echo 1 || echo 0 //在使用[]的时候-a 代替了
&&表示 and
0
[root@server2 ~]# touch file;touch dir
[root@server2 ~]# [ -f file -a -d dir ] && echo 1 || echo 0
0
[root@server2 ~]# touch file;mkdir dir
[root@server2 ~]# [[ -f file && -d dir ]] && echo 1||echo 0
1
[root@server2 ~]# [ -f file -a -d dir ] && echo 1 || echo 0
1
注:和-a 相对的是-o,和&&相对的是||
1.2)文件测试操作符
在书写测试表达式时,可以使用下表中的文件测试操作符
常用文件测试操作符号
常用文件测试操作符号的记忆方法:
[root@server2 ~]# echo f=file
f=file
[root@server2 ~]# echo d=directory
d=directory
[root@server2 ~]# echo s=exist
s=exist
[root@server2 ~]# echo r=read
r=read
[root@server2 ~]# echo w=write
w=write
[root@server2 ~]# echo x=executable
x=executable
[root@server2 ~]# echo nt="newer than"
nt=newer than
[root@server2 ~]# echo ot="older than"
ot=older than
1.3)字符串测试操作符
字符串测试操作符的作用:比较两个字符串是否相同、字符串长度是否为零,
字符串是否为 NULL(注:bash 区分零长度字符串和空字符串)等。
“=”比较两个字符串是否相同,与==等价,如 if[ “$a” = “$b” ],其中$a 这样的
变量最好用“”括起来,因为如果中间有空格、*等符号就可能出错了,当然更好的
方法就是[ “${a}” = “${b}” ]。“!=”比较两个字符串是否相同,不同则为“是”。
字符串测试操作符
字符串测试操作符提示:
1)-n 比较字符串长度是否不为零,如果不为零则为真,如:[ -n “myvar” ]
2)-z 比较字符串长度是否等于零,如果等于零则为真,如:[ -z “myvar” ]
1.4)整数二元比较操作符
在书写测试表达式时,可以使用下表中的整数二元比较操作符
整数二元比较操作符
提示:
1)“<”符号意思是小于,if[[ “$a” < “$b” ]],if[[ “$a” \< “$b” ]]。在单[]中需要转
义,因为 shell 也用<和>重定向
2)“>”符号意思是大于,if[[ “$a” > “$b” ]],if[[ “$a” \> “$b” ]]。在单[]中需要转
义,因为 shell 也用<和>重定向
3)“=”符号意思是等于,if[[ “$a” = “$b” ]] if[[ “$a” = “$b” ]] 在[]中不需要转
义
特别提示:
经过实践,“=”和“!=”在[]中使用不需要转义,包含“>”和“<”的符号在[]中使用
需要转义,对于数字不转义的结果未必会报错,但是结果可能不会对。
范例 1:二元数字比较
[root@server2 ~]# [ 2 > 1 ] && echo 1 || echo 0
1
[root@server2 ~]# [ 2 < 1 ] && echo 1 || echo 0
1
[root@server2 ~]# [ 2 \< 1 ] && echo 1 || echo 0
0
[root@server2 ~]# [ 2 \> 1 ] && echo 1 || echo 0
1
[root@server2 ~]# [ 2 -gt 1 ] && echo 1 || echo 0
1
[root@server2 ~]# [ 2 \> 1 ] && echo 1 || echo 0
1
[root@server2 ~]# [[ 2 < 1 ]] && echo 1 || echo 0
0
[root@server2 ~]# [[ 2 > 1 ]] && echo 1 || echo 0
1
[root@server2 ~]# [[ 2 = 1 ]] && echo 1 || echo 0
0
[root@server2 ~]# [ 2 = 2 ] && echo 1 || echo 0
1
[root@server2 ~]# [ 2 != 2 ] && echo 1 || echo 0
0
提示:经过实践,“=”和“!=”在[]中使用不需要转义也可以
[root@server2 ~]# [[ 2 -lt 1 ]] && echo 1 || echo 0
0
[root@server2 ~]# [[ 2 -gt 1 ]] && echo 1 || echo 0
1
范例 2:二元字符比较
[root@server2 ~]# [ "a" < "bc" ] && echo 1 || echo 0
1
[root@server2 ~]# [ "a" > "bc" ] && echo 1 || echo 0
1
上面两个条件不一样,但结果一样,虽然没报语法错误,但显然不对。
[root@server2 ~]# [ "a" \> "bc" ] && echo 1 || echo 0
0
[root@server2 ~]# [ "a" \< "bc" ] && echo 1 || echo 0
1
1.5)逻辑操作符
在书写测试表达式时,可以使用表中的逻辑操作符实现复杂的条件测试
逻辑链接符
提示:
!中文意思是反:与一个逻辑值相反的逻辑值
-a 中文意思是与(and &&):两个逻辑值都为“真”,返回值才为“真”,反
之为“假”
-o 中文意思是或(or ||):两个逻辑值只要有意各为“真”,返回值就为“真”
2)条件测试举例
下面举一些条件测试的例子。为了清晰的显示测试结果,我们在屏幕上输出 1(表
示真)或 0(表示假)表示测试结果
提示:这和前面的状态变量“$?”返回 0 为真不一样!
[ -f “$file” ] && echo 1 || echo 0
//这是条件表达式的用法
If [ -f “$file” ];then echo 1;else echo 0;fi
提示:
1.以上两条语句的功能是等同的。
2.变量$file 加了双引号,这时编程的好习惯,可以防止很多意外的错误发生
1.1)文件测试举例
首先我们定义 file1 和 file2 两个变量,并的你别赋予两个系统文件路径及文件名的
值。
[root@server2 ~]# file1=/etc/services;file2=/etc/rc.local
[root@server2 ~]# echo $file1 $file2
/etc/services /etc/rc.local
[root@server2 ~]# [ -f "$file1" ] && echo 1 || echo 0
1
[root@server2 ~]# [ -d "$file1" ] && echo 1 || echo 0
0
[root@server2 ~]# [ -f "$file2" ] && echo 1 || echo 0
1
[root@server2 ~]# [ -d "$file2" ] && echo 1 || echo 0
0
[root@server2 ~]# [ -e "$file1" ] && echo 1 || echo 0
1
[root@server2 ~]# [ -e "$file2" ] && echo 1 || echo 0
1
[root@server2 ~]# [ -w "$file1" ] && echo 1 || echo 0
1
//这里我们测试的时候是在 root 用户下,root 用户具有超级权限,因此我
们切换到一个普通用户下测试
[root@server2 ~]# su hy
[hy@server2 root]$ [ -w "$file1" ] && echo 1 || echo 0
0
注意下面的测试,“”号的有无,这里 file7 这个变量没有被定义
[root@server2 ~]# [ -f "$file7" ] && echo 1 || echo 0
0
[root@server2 ~]# [ -f $file7 ] && echo 1 || echo 0
1
可以看一下/etc/init.d/nfs
# Source networking configuration.
[ -f /etc/sysconfig/network ] && . /etc/sysconfig/network
# Check for and source configuration file otherwise set defaults
[ -f /etc/sysconfig/nfs ] && . /etc/sysconfig/nfs
# Remote quota server
[ -z "$RQUOTAD" ] && RQUOTAD=`type -path rpc.rquotad`
范例 4:多文件单中括号[]与或非测试
可用与(-a 和&&)
、或(-o 和||)、非(!)将多个条件表达式连接起来,接着上面
的变量测试。
[root@server2 ~]# file1=/etc/services;file2=/etc/init.d/nfs
[root@server2 ~]# [ -f "$file1" -a -e "$file2" ] && echo 1 || echo 0
0
[root@server2 ~]# [ -f "$file1" -o -e "$file2" ] && echo 1 || echo 0
1
[root@server2 ~]# [ -f "$file1" || "$file2" ] && echo 1 || echo 0
-bash: [: missing `]'
//这种用法是错误的使用下面的用法
-bash: /etc/init.d/nfs: 没有那个文件或目录
0
如果你非要使用单[]加&&或||那就用如下方法:
[root@server2 ~]# [[ -f "$file1" || "$file2" ]] && echo 1 || echo 0
1
[root@server2 ~]# [ -f "$file1" ] || [ -e "$file2" ] && echo 1 || echo 0
1
范例 5:双中括号多条件文件与或非测试
[root@server2 ~]# [[ -f "$file1" && -e "$file2" ]] && echo 1 || echo 0
0
[root@server2 ~]# [[ -f "$file1" -a -e "$file2" ]] && echo 1 || echo 0 //也不能这么用
-bash: syntax error in conditional expression
-bash: syntax error near `-a'
范例 6(生产):系统 bind 启动脚本举例:named(bind dns 服务)
在做测试判断时,不一定非要按照前面的方法。直接用后者做测试判断有时更简洁。
例如:
[root@server2 ~]# [ -f "$file1" ] && echo 1
1
[root@server2 ~]# [[ -f "$file1" && -e "$file2" ]] || echo 0
0
系统范例:/etc.init.d/nfs
[ -x /usr/sbin/rpc.nfsd ] || exit 5
[ -x /usr/sbin/rpc.mountd ] || exit 5
[ -x /usr/sbin/exportfs ] || exit 5
范例 8:学生学习问答案例:判断条件后执行多条命令语句。
[判断] || 命令 1 && 命令 2 && 命令 3,现在是如果前面条件成立了,也会执行命
令 2 和命令 3!
我想让后面的命令都不执行,我们可以用一个{}将后面的命令括起来
就实现了下面的功能:
if [ 条件 ]
then
do someting
else
命令 1
命令 2
命令 3
fi
例如:
[ 3 -ne 3 ] || {
echo “I am oldboy”
echo “I am coming”
exit 1
}
如果写在一行里面,里面的每个命令还需要用分号结尾,如下所示:
[ 3 -ne 3 ] || { echo “I am hy”; echo “I am coming”; exit 1; }
提示:本例的用法很简洁,但是理解起来不如 if 条件句容易,因此,请读者根据
自身情况使用。
拓展:
1)结尾小括号用法:
[ $ERROR -eq 0 ] && “jdk 安装成功!” || ( echo “jdk 安装失败,请检测!” &&
exit 1 )
2)结尾中括号用法:
[ $ERROR -eq 0 ] && “jdk 安装成功!” || [ echo “jdk 安装失败,请检测!” &&
exit 1 ]
3)结尾大括号用法:
[ $ERROR -eq 0 ] && “jdk 安装成功!” || { echo “jdk 安装失败,请检测!” &&
exit 1 }
[ $ERROR -eq 0 ] && “jdk 安装成功!” || {
echo “jdk 安装失败,请检测!”
exit 1
}
1.2)字符串测试举例
[root@server2 ~]# [ -n "$file" ] && echo 1||echo 0
0
//这里-n 指长度不为零
[root@server2 ~]# [ -z "$file" ] && echo 1||echo 0
1
//这里-z 指长度为零
去掉双引号试试:
[root@server2 ~]# [ -z $file ] && echo 1||echo 0
1
[root@server2 ~]# [ -n $file1 ] && echo 1||echo 0
1
特别强调:字符串比较要加双引号。
范例 2(生产):系统脚本/etc/init.d/nfs 字符串测试的应用:
# Remote quota server
[ -z "$RQUOTAD" ] && RQUOTAD=`type -path rpc.rquotad`
[ -z "$MOUNTD_NFS_V2" ] && MOUNTD_NFS_V2=default
[ -z "$MOUNTD_NFS_V3" ] && MOUNTD_NFS_V3=default
# Number of servers to be started by default
[ -z "$RPCNFSDCOUNT" ] && RPCNFSDCOUNT=8
范例 3:多条件字符串测试
[root@hy ~]# [ -z "$file1" -a -n "$file"] && echo 1 || echo 0
0
[root@hy ~]# [ -z "$file1" ] && echo 1 || echo 0
1
[root@hy ~]# [[ -z "$file1" && -n "$file" ]] && echo 1 || echo 0
0
[root@hy ~]# [[ -z "$file1" || -n "$file" ]] && echo 1 || echo 0
1
[root@hy ~]# [ "$file" = "$file" ] && echo 1 || echo 0
1
[root@hy ~]# [ "$file" != "$file"] && echo 1 || echo 0
0
[root@hy ~]# file1=/etc/services
[root@hy ~]# file2=/etc/rc.local
[root@hy ~]# [ "${#file1}" = "${#file2}" ] && echo 1 || echo 0
1
//两边字符串的长度是否相等
[root@hy ~]# [ "${file1}" = "${file2}" ] && echo 1 || echo 0
0
//两边的字符串是否相等
2.3)整数测试举例:
范例 1:整数条件测试举例
[root@server2 ~]# a1=10;a2=13
[root@server2 ~]# [ $a1 -eq $a2 ] && echo 1 || echo 0
0
[root@server2 ~]# [ $a1 -gt $a2 ] && echo 1 || echo 0
0
[root@server2 ~]# [ $a1 -lt $a2 ] && echo 1 || echo 0
1
[root@server2 ~]# [ "$a1" -ge "$a2" ] && echo 1 || echo 0
0
[root@server2 ~]# [ "$a1" -le "$a2" ] && echo 1 || echo 0
1
范例 2:直接通过数学运算符比较
这里不再讲解,另外注意有的运算符需要转义
提示:“=”和“==”也可以用于[]中。
2.4)test 命令测试的用法
范例 1:用 test 命令测试字符串
[root@server2 ~]# test -z "$file1" || echo 0
0
[root@server2 ~]# test -z "$file1" && echo 1|| echo 0
0
[root@server2 ~]# [ -z "$file1" ]&& echo 1|| echo 0
0
[root@server2 ~]# test -n "$file1" && echo 1|| echo 0
1
范例 2:用 test 命令测试真书比较
[root@server2 ~]# test "dd" == "ff" && echo 1 || echo 0
0
[root@server2 ~]# test "dd" == "dd" && echo 1 || echo 0
1
[root@server2 ~]# test "dd" != "dd" && echo 1 || echo 0
0
结论:test 命令测试的功能很强大,但是和[],[[]]之前都是重合的功能,因此,在
实际工作中我们选择一种适合我们自己的语法就 ok 了,其他的语法,别人写的脚本可
以阅读就可以了。
2.5)逻辑操作符的举例
其实前面的内容已经有提到逻辑操作符的使用了。1.5 逻辑操作符也说明了。
范例 1:&&和-a 与逻辑符脚本例子
#!/bin/bash
echo -n "请输入两个数字[格式为:m n]":
read m n
第一种写法:
if [ ${m} -eq 1 ] && [ ${n} -eq 2 ];then
echo "good"
else
echo "bad"
fi
第二中写法:
if [ ${m} -eq 1 -a ${n} -eq 2 ];then
echo "good1"
else
echo "bad1"
fi
第三种写法:
if [[ ${m} -eq 1 && ${n} -eq 2 ]];then
echo "good1"
else
echo "bad1"
fi
范例 2:||和-o 或逻辑符的脚本例子
[root@server2 ~]# [[ -z "$file1" || -z "file2" ]] && echo 1 || echo 0
0
[root@server2 ~]# [[ -z "$file1" || -n "file2" ]] && echo 1 || echo 0
1
[root@server2 ~]# [ -z "$file1" -o -z "file2"] && echo 1 || echo 0
0
范例 3:!非逻辑符的例子
[root@server2 ~]# [ ! -z "$file1" -o -z "file2" ] && echo 1 || echo 0
1
[root@server2 ~]# [[ ! -z "$file1" || ! -z "file2" ]] && echo 1 || echo 0
1
[root@server2 ~]# [[ ! -z "$file1" && ! -z "file2" ]] && echo 1 || echo 0
1
例子:利用 read 和 cat 打印选择菜单
#!/bin/bash
echo "1.[install lamp]"
echo "2.[install lnmp]"
echo "3.[install nfs]"
echo "4.[install rsync]"
read -p "please input then num that you want:" num
case $num in
1)
echo "[install lamp]"
;;
2)
echo "[install lnmp]"
;;
3)
echo "[install nfs]"
;;
4)
echo "[install nfs]"
;;
*)
echo "please reinput:"
esac
第二种写法:
menu(){
cat <
1.[install lamp]
2.[install lnmp]
3.[install nfs]
4.[install rsync]
please input the num that you want:
END
}
menu
read a
echo "you selected $a"
第三种写法多级菜单:
menu(){
cat <
1.[install lamp]
2.[install lnmp]
3.[install nfs]
4.[install rsync]
please input the num that you want:
END
}
menu
read a
[ $a -eq 1 ] && {
cat <
[1.install apache]
[2.install mysql]
[3.install php]
END
}
read b
echo "you want to $b"
http://skyex.blog.51cto.com/5935088/1176453 李灿
写 lamp 的安装脚本
3.if 条件句
1.1if 条件句语法说明
a)单分支结构
if[条件]
then
指令
fi
或
if[条件];then
指令
fi
多分支结构:
if 条件
then
指令
else
指令
fi
多分支结构:
if 条件
then
指令
elif 条件
then
指令
else
指令
fi
提示:分号相当于命令换行,上面两种语法等同。
特殊写法:if[ -f “$file1” ];then echo 1;fi 相当于:[ -f “$file1” ] && echo 1
范例 1:单分支 if 条件句整数比较大小
两个整数之间的比较:
#!/bin/bash
read a b
if [ $a \> $b ]
//或 if [ $a -gt $b ]
then
echo "max is a=$a"
else
echo "max is b=$b"
fi
两个字符串之间的比较:
例:判断一个文件是否存在,如果不存在,创建它
第一种写法:
#!/bin/bash
read a
if [ "`ls /root/ | grep $a`" == $a ]
then
echo "$a is exist"
else
{
echo "$a is not exist,it will be create by $USER"
touch /$USER/$a
}
fi
第二种写法:
#!/bin/bash
DIR="$USER"
read FILE
if [ -e /$DIR/$FILE ]
then
echo "$FILE is exist"
else
//if [ ! -e /$DIR/$FILE ]
{
echo "$FILE is not exist,it will be create by $USER"
touch /$USER/$FILE
}
fi
第三种写法:
#!/bin/bash
FILEPATH="/server/scripts"
if [ -d "$FILEPATH" ]
then
if [ -e $FILEPATH/if3.sh ]
then
echo "if3.sh is exist"
else
touch $FILEPATH/if3.sh
echo “if3.sh make cpmlete...successed.”
fi
else
{
mkdir -p $FILEPATH
touch $FILEPATH/if3.sh
echo “if3.sh make cpmlete...successed.”
}
fi
如果不想用上面的 else,还想用 if,写法如下:
if [ -e "$FILEPATH/if3.sh" ]
then
echo "$FILEPATH/if3.sh is exist"
fi
if [ ! -d "$FILEPATH" ]
then
mkdir -p $FILEPATH && touch $FILEPATH/if3.sh
fi
检测磁盘使用量:
#!/bin/bash
a=`df -m | grep root |awk '{print $4}'`
if (( $a < 100M ))
then
echo "/ litte 100M"
else
echo "/ more than 100M"
fi
检测内存使用量:
[root@server2 ~]# free -m | awk '/cache\:/ {print $NF}'
438
[root@server2 ~]# free -m | grep buffers |awk '{print $4}'| grep ^[0-9]
437
上面两种方法都是可以的,在执行效率上第一种方法比较好
#!/bin/bash
a=`free -m | grep buffers |awk '{print $4}'| grep ^[0-9]'`
if (( $a < 100 ))
then
echo "/ litte 100M"
else
echo "/ more than 100M"
fi
检测系统内存剩余量,如果小于 1000M 发送邮件给系统管理员
#!/bin/bash
cur_free=`free -m | grep buffers |awk '{print $4}'| grep ^[0-9]`
chars="current memory is $cur_free"
if (( $cur_free < 1000 ))
then
echo $chars
echo $chars | mail -s "$chars" 1020659371@qq.com
fi
crontab -e
* * * * * /bin/sh /root/memery.sh >&/dev/null
多分支举例:
a=$1
b=$2
if [ $# -ne 2 ]
then
echo "Usage:sh $0 num1 num2"
exit 1
fi
if [ $a -gt $b ]
then
echo "yes,$a > $b"
elif [ $a -eq $b ]
then
echo "yes,$a = $b"
else
echo "yes,$a < $b"
fi
加入对数字的判断:
a=$1
b=$2
if [ $# -ne 2 ]
then
echo "Usage:sh $0 num1 num2"
exit 1
fi
[ -n "`echo $1 | sed 's/[0-9]//g'`" ] && echo "第 一 个 参 数 必 须 为 数 字 " &&
exit 1
[ -n "`echo $2 | sed 's/[0-9]//g'`" ] && echo "第 二 个 参 数 必 须 为 数 字 " &&
exit 1
if [ $a -gt $b ]
then
echo "yes,$a > $b"
elif [ $a -eq $b ]
then
echo "yes,$a = $b"
else
echo "yes,$a < $b"
fi
扩展:判断字符串是否为数字的多种方法
法一:sed 加正则表达式
命令行传参:
组合语法判断 1:
[ -n "`echo $num |sed 's/[0-9]//g'`" -a -n "`echo $2 | sed 's/[0-9]//g'`" ] && echo "两个参
数都必须为数字" && exit 1
组合语法判断 2:
[ -n "`echo $num |sed 's/[0-9]//g'`" -a -n "`echo $2 | sed 's/[0-9]//g'`" ] && {
echo "两个参 数都必须为数字"
exit 1
}
普通变量判断:
[ -n "`echo $num |sed 's/[0-9]//g'`" ] &&echo "第二个参数都必须为数字" && exit 1
条件表达式,大括号的用法
[ -n "`echo $num |sed 's/[0-9]//g'`" ] && {
echo "第二个参数都必须为数字"
exit 1
}
法二:变量的子串替换加正则表达式
[root@server2 ~]# num=hy2015
[root@server2 ~]# [ -z "`echo "${num//[0-9]/}"`" ] && echo 1 || echo 0
0
[root@server2 ~]# num=2015hy2015
[root@server2 ~]# [ -z "`echo "${num//[0-9]/}"`" ] && echo 1 || echo 0
0
法三:变量的子串替换加正则表达式(特殊判断思路)
思路:如果 num 长度不为 0,并且把 num 中的非数字部分删除,然后看结果是不
是等于 num 本身,如果两者都成立就是数字。
-n "num" #->如果 num 长度不为 0 表达式
"$num" = "${num//^[0-9]/}" #->把 num 中的非数字部分删除,然后看结果是不是等
于 num 本身,如果两者都成立就是数字。
[root@server2 ~]# [ -n "$num" -a "$num" = "${num//[^0-9]/}" ] && echo "it is num"
测试:
[root@server2 ~]# num=2015
[root@server2 ~]# [ -n "$num" -a "$num" = "${num//[^0-9]/}" ] && echo "it is num"
it is num
法四:expr 计算判断
[root@server2 ~]# num=2015
[root@server2 ~]# expr $num + 0 >/dev/null 2>&1
[root@server2 ~]# [ $? -eq 0 ] && echo int
int
邮箱:g2hy@qq.com