Shell 变量的输入
Shell变量除了可以直接赋值或脚本传参外,还可以使用read命令从标准输入获得,read为bash内置命令,可以通过help read查看帮助
【语法格式】
read [参数] [变量名]
【常用参数】
-p prompt:设置提示信息
-t timeout:设置输入等待的事件,单位默认为秒
read的基本读入
如果我们不加-t read就会一直等待。
[root@web02 ~]# read -p "Pls input one num:" num Pls input one num:11
设置超时时间3秒
[root@web02 ~]# read -t 3 -p "Pls input one num:" num Pls input one num:[root@web02 ~]#
read 后面的参数就是一个变量。
[root@web02 ~]# read -t 18 -p "Pls input one num:" num Pls input one num:18 [root@web02 ~]# echo $num 18 其中此步骤相当于赋值,num=18
使用脚本操作步骤:
[root@web02 scripts]# sh abc.sh Pls input one num:18 18 [root@web02 scripts]# cat abc.sh #!/bin/bash read -t 18 -p "Pls input one num:" num echo $nu
read在脚本中常用的例子:
第一种方法
[root@web02 scripts]# sh abc.sh Pls input one num:1 2 1-2 =-1 1+2 =3 1*2 =2 1/2 =0 1**2 =1 1%2 =1 [root@web02 scripts]# cat abc.sh #!/bin/bash read -t 18 -p "Pls input one num:" 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 ))"
第二种方法
[root@web02 scripts]# sh b.sh 请输入号码:2 4 2+4 =6 2*4 =8 2/4 =0 2**4 =16 2%4 =2 [root@web02 scripts]# cat b.sh #!/bin/bash read -p "请输入号码": num1 num2 a=$num1 b=$num2 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命令替代和read -p的功能
[root@web02 scripts]# sh b.sh 请输入两个数字:2 5 2+5 =7 2*5 =10 2/5 =0 2**5 =32 2%5 =2 [root@web02 scripts]# cat b.sh #!/bin/bash echo -n "请输入两个数字:" 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 ))"
read 脚本常见的错误
[1]错误
[root@web02 scripts]# cat bash.sh #!/bin/bash a=$1 b=$2 read -p "pls input" echo "a-b =$(( $a - $b ))" echo "a+b =$(( $a + $b ))" echo "a*b =$(( $a * $b ))" 错误:read 后面没有变量,会造成下面无法引用。造成错误 在 read 添加 a b即可 ------------------------------------------------------- 正确操作如下 [root@web02 scripts]# cat bash.sh #!/bin/bash a=$1 b=$2 read -p "pls input" a b echo "a-b =$(( $a - $b ))" echo "a+b =$(( $a + $b ))" echo "a*b =$(( $a * $b ))"
[2] 错误
[root@web02 scripts]# cat bash.sh #!/bin/bash a=$1 b=$2 read -p "pls input" $1 $2 echo "a-b =$(( $a - $b ))" echo "a+b =$(( $a + $b ))" echo "a*b =$(( $a * $b ))" 错误:其中read 后面的$1 已经有了变量,不能重复使用
[3] 错误
[root@web02 scripts]# cat bash.sh #!/bin/bash a=$1 b=$2 read -p "pls input" $a read -p "pls input" $b echo "a-b =$(( $a - $b ))" echo "a+b =$(( $a + $b ))" echo "a*b =$(( $a * $b ))" 错误: 1. 首先read 这样写会比较麻烦,相当于输入一个2 还需要在输入一个2 才可以输出 2.read 已经是一个变量了,不可以在定义a=$1
实战:判断输入2个数是否是整数
[root@web02 scripts]# sh abc.sh 请输入2个数字:6 0 6-0 =6 6+0 =6 6*0 =0 0=0 can not be 0,so /,% cat not yunsuan 6**0 =1 [root@web02 scripts]# sh abc.sh 请输入2个数字:6 9 6-9 =-3 6+9 =15 6*9 =54 6/9 =0 6%9 =6 6**9 =10077696 [root@web02 scripts]# sh abc.sh 请输入2个数字:a b 请输入整数 [root@web02 scripts]# sh abc.sh 请输入2个数字:a 8 请输入整数 [root@web02 scripts]# sh abc.sh 请输入2个数字:8 8 8 请输入整数 ====================================== 脚本内容: [root@web02 scripts]# cat abc.sh #!/bin/bash read -t 18 -p "请输入2个数字:" a b #no.1 [ -z "$a" ]&&{ echo "必须为整数" exit 1 } [ -z "$b" ]&&{ echo "输入两个整数" exit 2 } #no.2 expr $a + $b + 1 &>/dev/null [ $? -ne 0 ]&&{ echo "请输入整数" exit 3 } #no.3 echo "$a-$b =$(( $a - $b ))" echo "$a+$b =$(( $a + $b ))" echo "$a*$b =$(( $a * $b ))" if [ $b -eq 0 ];then echo "$b=0 can not be 0,so /,% cat not yunsuan" else echo "$a/$b =$(( $a / $b))" echo "$a%$b =$(( $a % $b))" fi echo "$a**$b =$(( $a ** $b ))"
条件测试与比较
在bash的各种流程控制结构中通常要进行各种测试,然后根据测试结果执行不同的操作,有时也会通过与if等条件语句相结合,更方便的完成判断
条件测试通常由如下3种语法形式:
语法1:test<测试表达式>
语法2:[<测试表达式>]
语法3:[[<测试表达式>]]
说明:
1.上述语法格式1和语法格式2的写法是相等的。语法格式3为扩展的test命令。推荐使用语法格式2
2.在[[]]中可以使用通配符进行模式匹配。&&、||、>、<等操作可以应用于[[]]中,但不能应用于[]中
3.对于整数的关系运算,也可以使用Shell的算术运算符(())
test测试表达式
1.判断是不是文件 [root@web02 scripts]# test -f /etc/hosts &&echo 1||echo 0 1 [root@web02 scripts]# test -f /etc/hostsa &&echo 1||echo 0 0 2.判断文件是否可以执行 [root@web02 scripts]# test -x /server/scripts/abc.sh &&echo 1||echo 0 0 [root@web02 scripts]# chmod +x abc.sh [root@web02 scripts]# test -x /server/scripts/abc.sh &&echo 1||echo 0 1 3.判断是不是目录 [root@web02 scripts]# test -d /etc/ &&echo 1||echo 0 1 [root@web02 scripts]# test -d /etc/hosts &&echo 1||echo 0 0 4.是否为空,为空是真,不为空是假 [root@web02 scripts]# test -z "oldboy"&& echo 1||echo 0 0 [root@web02 scripts]# test -z ""&& echo 1||echo 0 1
[]中括号表达式
1、判断是不是普通文件 [root@web02 scripts]# [ -f /etc/hosts ]&&echo 1||echo 0 1 [root@web02 scripts]# [ -f /etc/host ]&&echo 1||echo 0 0 2、是否是目录 [root@web02 scripts]# [ -d /etc/host ]&&echo 1||echo 0 0 [root@web02 scripts]# [ -d /etc/ ]&&echo 1||echo 0 1 3、是否可执行 [root@web02 scripts]# [ -x /etc/hosts ]&&echo 1||echo 0 0 [root@web02 scripts]# [ -x /server/scripts/abc.sh ]&&echo 1||echo 0 1
[[]]双括号表达式
[root@web02 scripts]# [[ -x /server/scripts/abc.sh ]]&&echo 1||echo 0 1 [root@web02 scripts]# [[ -x /etc/hosts ]]&&echo 1||echo 0 0
此括号和[[]]几乎和[]一样
区别是可以在多括号里面添加多个判断
例如判断是不是目录 ,并判断下一个文件是不是可执行
[root@web02 scripts]# [[ -d /etc/ && -f /server/scripts/abc.sh ]]&&echo 1||echo 0 1 [root@web02 scripts]# [[ -d /etc/ && -f /server/scripts/aabc.sh ]]&&echo 1||echo 0 0
当2个参数都成立的时候就输入echo 1 ,当不成立的时候echo 2
提示:&&只在双括号里生效,如果在单括号需要使用-a,双中括号或用|| 单括号使用-o
其中-a = and
-o = or
文件测试表达式
常用的文件测试操作符
操作符 说明 举例 -b file 检测文件是否是块设备文件,如果是,则返回 true。 [ -b $file ] 返回 false。 -c file 检测文件是否是字符设备文件,如果是,则返回 true。 [ -c $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。
特别说明:这些操作符号对于[[]]、[]、test几乎都是通用的,更多操作符请man test查询
例子:
测试文件是否存在
[root@web02 ~]# touch oldboy [root@web02 ~]# ls -l oldboy -rw-r--r-- 1 root root 0 Jul 8 07:28 oldboy [root@web02 ~]# [ -f oldboy ]&& echo 1 ||echo 0 1 [root@web02 ~]# [ -f oldboy1 ]&& echo 1 ||echo 0 0
测试目录
[root@web02 ~]# [ -d oldgirl ]&& echo 存在||echo 不存在 存在 [root@web02 ~]# [ -d oldgirl1 ]&& echo 存在||echo 不存在 不存在 测试是否存在 [root@web02 ~]# [ -e oldboy ]&& echo 存在||echo 不存在 存在 [root@web02 ~]# [ -e oldgirl ]&& echo 存在||echo 不存在 存在
测试文件属性
[root@web02 ~]# ls -l oldboy -rw-r--r-- 1 root root 0 Jul 8 07:28 oldboy [root@web02 ~]# [ -r oldboy ]&&echo 1||echo 2 1 [root@web02 ~]# [ -w oldboy ]&&echo 1||echo 2 1 [root@web02 ~]# [ -x oldboy ]&&echo 1||echo 2 2 [root@web02 ~]# chmod +x oldboy [root@web02 ~]# [ -x oldboy ]&&echo 1||echo 2 1
测试shell变量定义
[root@web02 ~]# file1=/etc/services [root@web02 ~]# file2=/etc/rc.local
对单个文件变量测试
[root@web02 ~]# [ -f $file1 ]&&echo 1||echo 0 1 [root@web02 ~]# [ -d $file2 ]&&echo 1||echo 0 0 最谨慎的操作步骤应该是加上双引号 [root@web02 ~]# [ -f "$file1" ]&&echo 1||echo 0 1 [root@web02 ~]# [ -d "$file2" ]&&echo 1||echo 0 0 提示:此处判断的是file2的变量的目录是否存在
生产场景案例:(例如rpcbind)
另一种写法
如果文件不存在,我就进行操作
[root@web02 ~]# [ -f "$file1" ]||echo 2 [root@web02 ~]# [ -f "$fil11e1" ]||echo 2 2
特殊文件测试表达式写法案例
条件表达式判断条件后面执行多条命令语句写法。
范例1:当条件1成立时,同时执行命令1、命令2、命令3.
用法:
[ 条件1 ]&&{
命令1
命令2
命令3
}
示例:
[root@web02 ~]# [ -f /etc/hosts ]&&{ echo 1;echo 2;echo 3;echo 3; } 1 2 3
等于3 执行什么操作
[root@web02 ~]# sh 1.sh 3 1 2 3 [root@web02 ~]# cat 1.sh #!/bin/bash [ $1 -eq 3 ]&&{ echo 1 echo 2 echo 3 }
可以使用条件表达式,大括号的用法,格式如下。
当条件不成立时会执行大括号的内容
[ 3 -ne 3 ]||{ echo "I am ok" echo "I am no" exit 1 }
字符串表达式
字符串测试操作符的作用有:比较两个字符串是否相同、字符串的长度是否为零,字符串是否为NULL(注:bash区分零长度字符串和空字符串)等
常用字符串测试操作符 说明 -z "字符串" 若串长度为0则真,-z可以理解为zero -n ”字符串“ 若昂度不为0则真,-n 可以理解为no zero ”串1“ = ”串2“
若串1等于串2则真,可以使用”==“代替”=“
“串2” != “串2”
若串1不等于串2则真,不能用“!==“ 代替”!=“ 特别注意:
1. 以上表格中的字符串测试操作符号务必要用”“引起来。
2.比较符号两端有空格
字符串测试操作符提示:
1)-n 比较字符串长度是否不为零,如果不为零则为真,如:[ -n "$myvar" ]
2)-z 比较字符串长度是否等于零,如果等于零则为真,如:[ -z "$myvar" ]
特别注意,对于以上表格中的字符串测试操作符号,如[ -n "$myvar" ],要把字符串用“”引起来。
注意事项
1、字符串或字符串变量比较都要加双引号之后再比较。
2、字符串或字符串变量比较,比较符号两端最好都有空格,可以参考系统脚本
“=”比较两个字符串是否相同,与“==”等价,如[ "$a" = "$b" ]其中$a这样的变量最好用“”括起来,因为如果中间由空格,*等符号就可能出错,更好的办法就是[ "${a}" = "${b}" ]
“!=” 比较两个字符串是否相同,不同则为“是”
[root@web02 ~]# [ -n "abc" ]&&echo 1||echo 0 1 [root@web02 ~]# [ -n "" ]&&echo 1||echo 0 0 [root@web02 ~]# [ -z abc"" ]&&echo 1||echo 0 0 [root@web02 ~]# [ ! -z abc"" ]&&echo 1||echo 0 1
其中!-z 相当于-n
例子演示
[root@web02 ~]# test=oldboy [root@web02 ~]# [ -n "$test" ]&&echo 1||echo 0 1 [root@web02 ~]# [ -z "$test" ]&&echo 1||echo 0 0
相等测试
[root@web02 ~]# [ "$test" = "oldboy" ]&&echo 1||echo 2 1 [root@web02 ~]# [ "$test" = "oldbo1y" ]&&echo 1||echo 2 2
整数二元比较操作符
在[]以及test 中会用的比较符号 在(())和[[]]中使用的比较符 说明 -eq ==或== equal的偶写,相等 -ne != not equal的缩写,不相等 -gt > 大于greater than -ge >= 大于等于greater equal -lt < 小于类似less than -le <= 小于等于less equal 更多参数可以使用man test
例子演示
[root@web02 ~]# [ 2 -eq 1 ]&&echo 1||echo 0 0 [root@web02 ~]# [ 2 -ne 1 ]&&echo 1||echo 0 1 [root@web02 ~]# [ 2 -gt 1 ]&&echo 1||echo 0 1 [root@web02 ~]# [ 2 -ge 1 ]&&echo 1||echo 0 1 [root@web02 ~]# [ 2 -lt 1 ]&&echo 1||echo 0 0 [root@web02 ~]# [ 2 -le 1 ]&&echo 1||echo 0 0
特别提示:
经过实践,“=”和“!=”在[]中使用不需要转移,包含“>”和“<”的符号在[]中使用需要转移,对于数字不转义的结果未必会报错,但是结果可能不对
实际测试结果结论:
1、整数加双引号也是对的。
2、[[]]用-eq等的写法也是对的,[[]]用>写法也可能不对,只比较第一位,逻辑结果不对。
3、[]用>号的写法语法没错,逻辑结果不对。
工作场景:推荐[]的-eq的用法。
[root@web02 ~]# grep -w "-eq" /etc/init.d/nfs [ $RETVAL -eq 0 ] && RETVAL=$rval [ $RETVAL -eq 0 ] && RETVAL=$rval [ $RETVAL -eq 0 ] && RETVAL=$rval [ $RETVAL -eq 0 ] && RETVAL=$rval [ $RETVAL -eq 0 ] && RETVAL=$rval
逻辑操作符
在[]和test中使用 在[[]]中使用 说明 -a && and与,两端都为真,则真 -o || or或,两端有一个为真则真 ! ! not非,相反则为真
提示:
!中文意思是反:与一个逻辑值相关的逻辑值
-a 中文意思是(and|&&):两个逻辑值都为“真”,返回值才为“真”,反之为“假”
-o 中文意思是或(or| ||):两个逻辑值只要有一个为“真”,返回值就为“真”
逻辑操作运算规则
结论:-a和&& 的运算规则:只有两端都是1才为真
真true 假false
举个例子
[root@web02 ~]# f1=/etc/rc.local;f2=/etc/services [root@web02 ~]# [ -f "$f1" -a -f "$f2" ]&&echo 1||echo 0 1
如果使用&&就会报错
[root@web02 ~]# [ -f "$f1" && -f "$f2" ]&&echo 1||echo 0 -bash: [: missing `]' 0
要想使用&&就加双括号
[root@web02 ~]# [[ -f "$f1" && -f "$f2" ]]&&echo 1||echo 0 1 ================================== [root@web02 ~]# [ $a -eq 2 -a $b -eq 2 ]&&echo 1||echo 0 0 [root@web02 ~]# [ $a -eq 1 -a $b -eq 2 ]&&echo 1||echo 0 1 [root@web02 ~]# [ $a -eq 3 -a $b -eq 3 ]&&echo 1||echo 0 0 [root@web02 ~]# [ $a -eq 3 -o $b -eq 3 ]&&echo 1||echo 0 0 [root@web02 ~]# [ $a -eq 1 -o $b -eq 3 ]&&echo 1||echo 0 1 [root@web02 ~]# [[ $a -eq 1 || $b -eq 3 ]]&&echo 1||echo 0 1
系统案例:
[root@web02 ~]# sed -n '87,90p' /etc/init.d/nfs [ "$NFSD_MODULE" != "noload" -a -x /sbin/modprobe ] && { /sbin/modprobe nfsd [ -n "$RDMA_PORT" ] && /sbin/modprobe svcrdma }
小结:逻辑操作符使用总结
[]中用-a,-o,!
[[]]中用&&,||,!
test用法和[]相同
多个[]之间以及多个[[]]之间,或者任意混合中间逻辑操作符都是&&或||
特别声明:有关test,[],[[]]的操作符的用法,help test或man test查询第一手帮助。
综合实战案例:开发Shell脚本分别实现以定义变量,脚本传参以及read读入的方式比较2个整数大小。用条件表达式(禁止if)进行判断并以屏幕输出的方式提醒用户比较结果。注意。一共是开发3个脚本。当用脚本传参以及read读入的方式需要对变量是否为数字、并且传参个数不对给予提示。
第一种方法:
[root@web02 ~]# cat 1212.sh #!/bin/sh #no.1 [ $# -ne 2 ]&&{ echo "USAGE:$0 num1 num2" exit 1 } #no.2 a=$1 b=$2 expr $a + 1 &>/dev/null [ $? -ne 0 ]&&{ echo "First arg must be int." exit 2 } expr $b + 1 &>/dev/null [ $? -ne 0 ]&&{ echo "Second arg must be int." exit 3 } #no.3 [ $a -gt $b ]&&{ echo "$a > $b" exit 0 } [ $a -eq $b ]&&{ echo "$a = $b" exit 0 } [ $a -lt $b ]&&{ echo "$a < $b" exit 0 }
第二种方式:
[root@web02 ~]# cat www.sh #!/bin/sh #no.1 read -p "Pls input two num:" a b [ -z "$a" -o -z "$b" ]&&{ echo "must be two num." exit 1 } #no.2 expr $a + 1 &>/dev/null [ $? -ne 0 ]&&{ echo "First arg must be int." exit 2 } expr $b + 1 &>/dev/null [ $? -ne 0 ]&&{ echo "Second arg must be int." exit 3 } #no.3 [ $a -gt $b ]&&{ echo "$a > $b" exit 0 } [ $a -eq $b ]&&{ echo "$a = $b" exit 0 } [ $a -lt $b ]&&{ echo "$a < $b" exit 0 }
综合案例:打印选择菜单
[root@web02 scripts]# cat install.sh #!/bin/bash . /etc/init.d/functions export PATH menu(){ cat < 因为此脚本比较简单,我不详细介绍。下面可以看一下操作,因为很多地方没有定义直接设置为空,还需完善
分支与循环结构 [1] 单分支结构 语法: if [ 条件 ] then 指令 fi 或 if [ 条件 ];then 指令 fi [2] 双分支结构 语法: if [ 条件 ] then 指令集1 else 指令集2 fi [3] 多分支结构 语法: if 条件1 then 指令1 elif 条件2 then 指令2 else 指令3 fi ----- if 条件 then 指令 elif 条件 then 指令 elif 条件 then 指令 ... ... else 指令 fi 范例2:开发shell脚本判断系统剩余内存的大小,如果低于100M就邮件报警给管理员,并且系统定时任务每3分支执行一次检查。 思路: 1.分析需求 2.简单设计 a.取当前内存大小 b.判断是否大于10m,如果小于100M,就报警 c.加入定时任务,每三分钟检查一次 3.编码实现 [root@db01 scripts]# cat free.sh #!/bin/sh mem=$(free -m|awk 'NR==3{print $NF}') if [ $mem -lt 1000 ] then echo "mem is not enough. $mem" echo "mem is not enough. $mem"|mail -s "`date` mem is not enough" 31333741-@qq.com else echo ok fi [root@db01 scripts]# crontab -l #time sync by oldboy at 2010-2-1 */5 * * * * /usr/sbin/ntpdate time.nist.gov >/dev/null 2>&1 ########### */3 * * * * /bin/sh /server/scripts/free.sh >/dev/null 2>&1 范例:使用read及脚本传参方式如何实现2个整数比较大小? 解答: 特别强调:read读入和命令行传参是两种输入内容的方法(两个脚本) [root@db01 scripts]# cat read.sh #!/bin/sh #no.1 read -p "Pls input two num:" a b [ -z "$a" -o -z "$b" ]&&{ echo "must be two num." exit 1 } #no.2 expr $a + 1 &>/dev/null [ $? -ne 0 ]&&{ echo "First arg must be int." exit 2 } expr $b + 1 &>/dev/null [ $? -ne 0 ]&&{ echo "Second arg must be int." exit 3 } #no.3 [ $a -gt $b ]&&{ echo "$a > $b" exit 0 } [ $a -eq $b ]&&{ echo "$a = $b" exit 0 } [ $a -lt $b ]&&{ echo "$a < $b" exit 0 }
相关文章:
- Shell 基础介绍 [1]
- 老男孩Shell企业面试题30道 [答案]
- Shell 脚本案例实战 [4]
- Kubernetes 1.14 二进制集群安装