zoukankan      html  css  js  c++  java
  • shell编程:条件测试与比较(六)

    条件测试方法综述

    test条件测试的简单语法及测试

    范例6-1 测试文件(在test命令中使用-f选项:文件存在且为不同文件则表达式成立)

    [root@adminset ~]# test -f file && echo true || echo false
    false
    [root@adminset ~]# touch file
    [root@adminset ~]# test -f file && echo true || echo false
    true

    范例6-2 测试字符串(在test命令中使用-z选项(如果测试字符串的长度为0,则表达式成立)

    [root@adminset ~]# test -z "luoahong" && ehco 1 || echo 0
    0
    [root@adminset ~]# char="luoahong"
    0
    [root@adminset ~]# test -z "$char" && echo 1 || echo 0
    0
    [root@adminset ~]# char=""
    [root@adminset ~]# test -z "$char" && echo 1 || echo 0
    1

    结论:test命令测试的功能很强大,但是和[] [[]]的功能有所重合,因此,在实际工作中选择一种适合自己的语法就好了,对于其他的语法,能读懂别人写的脚本就可以了

    [](中括号)条件测试语法及示例

    范例6-3 测试文件(利用[]加-f 选项 文件存在且为普通文件则表达式成立)

    [root@adminset ~]# [ -f /tmp/luoahong.txt ] && echo 1 ||echo 0
    0
    [root@adminset ~]# touch /tmp/luoahong.txt
    [root@adminset ~]# [ -f /tmp/luoahong.txt ] && echo 1 ||echo 0
    1
    [root@adminset ~]# [ -f /tmp/luoahong.txt ] ||echo 0
    [root@adminset ~]# [ -f /tmp/luoahong1.txt ] ||echo 0
    0
    [root@adminset ~]# [ -f /tmp/luoahong1.txt ] ||echo 0
    0
    [root@adminset ~]# touch /tmp/luoahong1.txt
    [root@adminset ~]# [ -f /tmp/luoahong1.txt ] ||echo 0
    [root@adminset ~]# rm -f /tmp/luoahong1.txt
    [root@adminset ~]# [ -f /tmp/luoahong1.txt ] ||echo 0
    0

    提示:[]命令的选项和test的命令的选项是通用的,因此,使用[]时的参数选项可以通过man test命令获的帮助

    文件测试表达式

    范例6-5:文件属性条件表达式测试实践

    [root@adminset ~]# ls -l luoahong
    -rw-r--r-- 1 root root 0 Jun 14 07:48 luoahong
    [root@adminset ~]# [ -r luoahong ] && echo 1 ||echo 0
    1
    #测试luoahong是否可读
    
    [root@adminset ~]# [ -w luoahong ] && echo 1 ||echo 0
    1
    #测试luoahong是否可写
    [root@adminset ~]# [ -x luoahong ] && echo 1 ||echo 0
    0
    #测试luoahong是否可执行
    [root@adminset ~]# chmod 001 luoahong	
    [root@adminset ~]# ls -l luoahong
    ---------x 1 root root 0 Jun 14 07:48 luoahong
    #修改后的结果
    [root@adminset ~]# [ -w luoahong ] && echo 1 ||echo 0
    1
    #用户权限位明明没有w,为什么还是返回1呢?
    [root@adminset ~]# echo 'echo test' >oldboy
    #因为确实可以写啊,这是root用户比较特殊的地方
    [root@adminset ~]# [ -r luoahong ] && echo 1 ||echo 0
    1
    #用户权限位明明没有r,为什么还是返回1呢?
    [root@adminset ~]# echo 'echo test' >luoahong
    [root@adminset ~]#cat luoahong
    echo test
    #因为确实可以读啊,这是root用户比较特殊的地方。
    [root@adminset ~]# [ -x luoahong ] && echo 1 ||echo 0
    1
    [root@adminset ~]# ./luoahong
    [root@adminset ~]# ./luoahong
    test
    
    #可执行

    提示:测试文件的读、写、执行等属性,不光是根据文件属性rwx的表示来判断,

    还要看当前执行的用户是否真的可以按照对应的权限操作该文件

    测试shell变量示例

    root@adminset ~]# file1=/etc/services;file2=/etc/rc.local
    [root@adminset ~]# echo $file1 $file2
    /etc/services /etc/rc.local

    范例:对单个文件变量进行测试

    [root@adminset ~]# [ -f "$file1" ] && echo 1 || echo 0
    1
    [root@adminset ~]# [ -d "$file1" ] && echo 1 || echo 0
    0
    [root@adminset ~]# [ -s "$file1" ] && echo 1 || echo 0
    1
    [root@adminset ~]# [ -e "$file1" ] && echo 1 || echo 0
    1
    [root@adminset ~]#
    [root@adminset ~]#

    范例:对单个目录或文件进行测试

    [root@adminset ~]# [ -e /etc ] && echo 1 || echo 0
    1
    [root@adminset ~]# [ -w /etc/serbices ] && echo 1 || echo 0
    0
    [root@adminset ~]# su - luoahong
    [luoahong@adminset ~]$ [ -w /etc/servies ] && echo 1 || echo 0
    0
    #文件不可写,所以返回0

    范例:测试变量的特殊写法及问题

    用测试变量时,如果被测试的变量不加双引号,那么测试结果可能会不时正确的示例如下:

    [luoahong@adminset ~]$ echo $tyx
    #这是一个不存在的变量,如果读者已经定义、则可以执行unset取消
    [luoahong@adminset ~]$ [ -f $tyx ] && echo 1 || echo 0
    1
    #命名$tyx变量不存在内容还返回1,逻辑就不对了
    [luoahong@adminset ~]$ [ -f "$tyx" ] && echo 1 || echo 0
    0
    #加了双引号就返回0,逻辑就对了

    如果是文件实体路径,那么加引号与不加引号的结果时一样的:

    [luoahong@adminset ~]$ [ -f "/etc/services" ] && echo 1 || echo 0
    1
    [luoahong@adminset ~]$ [ -f /etc/services ] && echo 1 || echo 0
    1

    范例: 在生产环境下,系统NFS启动脚本的条件测试

    more /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`

    特别提示:系统脚本时我们学习编程的第一标杆,新手要多参考脚本来学习,虽然有些脚本也不是特别规范

    范例:实现系统bind启动脚本named

    [luoahong@adminset ~]$ [ -r /etc/sysyconfig/network ] && ./etc/sysconfig/network
    #若文件存在且可读,则加载/etc/sysconfig/network
    [luoahong@adminset ~]$ [ -x /usr/sbin/$named ] || exit 5

    范例:写出简单高效的测试文件

    在做测试判断时,不一定非要按照"前面的操作成功了如何,否则如何"的方法来进行。直接做部分判断,有时看起来更简洁

    [luoahong@adminset ~]$ [ -x luoahong ] && echo 1
    #如果luoahong可执行,则输出1;如果不可执行,则不做任何输出
    [luoahong@adminset ~]$ [ -f /etc ] && echo 1
    [luoahong@adminset ~]$ [ -f /etc ] && echo 0
    #如果l/etc 是文件这一点不成立,则输出0,如果成立则不做任何输出

    范例:实现系统脚本/etc/init.d/nfs

    [luoahong@adminset ~]$ sed -n '44,50p' /etc/init.d/nfs
    # Check that networking is up.
    [ "${NETWORKING}" != "yes" ] && exit 6
    #如果${NETWORKING}的变量内容不等于yes,则退出
    
    [ -x /usr/sbin/rpc.nfsd ] || exit 5
    #如果/usr/sbin/rpc.nfsd的脚本不可执行,则以返回值5退出脚本。如果可执行,则不做任何输出
    [ -x /usr/sbin/rpc.mountd ] || exit 5
    [ -x /usr/sbin/exportfs ] || exit 5

    特殊表达式测试案例

    范例:当条件不成立是,执行大括号里的多条命令,这里要使用逻辑操作符||

    [root@adminset 06]# sh 6_15.sh
    1
    2
    3
    [root@adminset 06]# cat 6_15.sh
    [ -f /etc ] || {
    echo 1
    echo 2
    echo 3
    
    }
    
    [root@adminset 06]# sh 6_15.sh
    1
    2
    3

    如果上述脚本写在一行里面,那么里面的每个命令都需要用分号结尾,示例如下所示:

    [root@adminset 06]# [ -f /etc/services ] && { echo "I am luoahong"; echo "I am linuxer"; }
    
    I am luoahong
    I am linuxer

    提示:本例的两种用法都很简洁,但是不如if条件容易理解,因此请读者根据自身情况选择使用,更多帮助请man test查询

    字符串测试表达式

    字符串测试操作符

    范例:字符串条件表达式测试实践

    [root@adminset 06]# [ -n "abc" ] && echo 1 || echo 0
    1
    [root@adminset 06]# test -n "" && echo 1 || echo 0
    0
    [root@adminset 06]# var="luoahong"
    [root@adminset 06]# [ -n "$var" ] && echo 1 || echo 0
    1
    [root@adminset 06]# [ -n $var ] && echo 1 || echo 0
    1
    [root@adminset 06]# var="luoahong1"
    [root@adminset 06]# [ -z $var ] && echo 1 || echo 0
    0
    [root@adminset 06]# [ "abc" = "abd" ] && echo 1 || echo 0
    0
    [root@adminset 06]# [ "$var" = "luoahong1" ] && echo 1 || echo 0
    1
    [root@adminset 06]# [ "$var" == "luoahong1" ] && echo 1 || echo 0
    1
    [root@adminset 06]# [ "$var" != "luoahong1" ] && echo 1 || echo 0
    0

    字符串测试生产案例

    范例:有关双引号和等号两端空格的生产系统标准

    [root@adminset 06]# sed -n '30,31p' /etc/init.d/network
    #check that networking is up
    [ "${NETWORKING}" = "no" ] && exit 6
    #字符串变量和字符串都加了双引号,比较符号"="两端也都有空格

    范例:系统脚本/etc/init.d/nfs字符串测试的应用示例

    [root@adminset 06]# sed -n '65,80p' /etc/init.d/nfs
    [ -z "$MOUNTD_NFS_V2" ] && MOUNTD_NFS_V2=default
    #-z的应用,如果变量MOUNTD_NFS_V2的长度为0则赋值default
    [ -z "$MOUNTD_NFS_V3" ] && MOUNTD_NFS_V3=default
    #-z的应用,如果变量MOUNTD_NFS_V3的长度为0则赋值default
    # Number of servers to be started by default
    [ -z "$RPCNFSDCOUNT" ] && RPCNFSDCOUNT=8
    
    # Start daemons.
    [ -x /usr/sbin/rpc.svcgssd ] && /sbin/service rpcsvcgssd start
    
    # Set the ports lockd should listen on
    if [ -n "$LOCKD_TCPPORT" -o -n "$LOCKD_UDPPORT" ]; then #-n的应用
    [ -x /sbin/modprobe ] && /sbin/modprobe lockd $LOCKDARG
    [ -n "$LOCKD_TCPPORT" ] && 
    /sbin/sysctl -w fs.nfs.nlm_tcpport=$LOCKD_TCPPORT >/dev/null 2>&1
    [ -n "$LOCKD_UDPPORT" ] && 
    /sbin/sysctl -w fs.nfs.nlm_udpport=$LOCKD_UDPPORT >/dev/null 2>&1
    fi

    整数变量测试示例

    范例:通过[]实现整数条件测试

    [root@adminset 06]# a1=98;a2=99
    [root@adminset 06]# [ $a1 -eq $a2 ] && echo 1 ||echo 0
    0
    [root@adminset 06]# [ $a1 -gt $a2 ] && echo 1 ||echo 0
    0
    [root@adminset 06]# [ $a1 -lt $a2 ] && echo 1 ||echo 0
    1

    范例:利用[[]]和(())实现直接通过常规数学运算符进行比较

    [root@adminset 06]# [[ $a1 > $a2 ]] && echo 1 ||echo 0
    0
    [root@adminset 06]# [[ $a1 < $a2 ]] && echo 1 ||echo 0
    1
    [root@adminset 06]# (($a1>=$a2)) && echo 1|| echo 0
    0
    [root@adminset 06]# (($a1<=$a2)) && echo 1|| echo 0
    1

    范例:系统脚本中使用整数比较的案例

    [root@adminset ~]#grep -w "-eq" /etc/init.d/nfs
    [ $RETVAL -eq 0 ] && RETVAL=$rval #过滤出相等(-eq)的例子
    [ $RETVAL -eq 0 ] && RETVAL=$rval #使用[],且两边都要有一个空格
    [ $RETVAL -eq 0 ] && RETVAL=$rval #使用"-eq" 的比较操作符的写法
    [ $RETVAL -eq 0 ] && RETVAL=$rval
    [ $RETVAL -eq 0 ] && RETVAL=$rval
    
    [root@adminset ~]#grep -w "-gt" /etc/init.d/nfs #过滤出大于(-gt)的例子
    if [ $cnt -gt 0 ]; then

    逻辑操作符实践示例

    范例:[]里的逻辑操作配合文件测试表达式使用的示例

    [root@adminset 06]# f1=/etc/rc.local;f2=/etc/services
    [root@adminset 06]# echo -ne "$f1 $f2
    "
    /etc/rc.local /etc/services
    [root@adminset 06]# [ -f "$f1" -a -f "$f2" ] && echo 1 || echo 0
    1
    [root@adminset 06]# [ -f "$f1" -o -f "$f222" ] && echo 1 || echo 0
    1
    [root@adminset 06]# [ -f "$f111" -o -f "$f222" ] && echo 1 || echo 0
    0
    [root@adminset 06]# [ -f "$f1" && -f "$f2" ] && echo 1 || echo 0
    -bash: [: missing `]'
    0
    #这是错误的语法,[]中不能用&&||
    [root@adminset 06]# [ -f "$f1" ] && [ -f "$f2" ] && echo 1 || echo 0
    1
    #如果在[]中使用&&,则这样用

    范例:[[]]里逻辑操作符配合字符串的条件表达式的测试示例

    [root@adminset 06]# a="luoahong";b="tyx"
    [root@adminset 06]# echo -ne "$a $b
    "
    luoahong tyx
    [root@adminset 06]# [[ ! -n " $a" && "$a" = "$b"]] && echo 1 || echo 0
    -bash: conditional binary operator expected
    -bash: syntax error near `1'
    [root@adminset 06]# [[ ! -n "$a" && "$a" = "$b"]] && echo 1 || echo 0
    -bash: conditional binary operator expected
    -bash: syntax error near `1'
    [root@adminset 06]# [[ ! -n "$a" && "$a" = "$b" ]] && echo 1 || echo 0
    0
    [root@adminset 06]# [[ -z "$a" || "$a" != "$b" ]] && echo 1 || echo 0
    1
    [root@adminset 06]#
    [root@adminset 06]# [[ -z "$a" -o "$a" != "$b" ]] && echo 1 || echo 0
    -bash: syntax error in conditional expression
    -bash: syntax error near `-o'

    范例:(())里逻辑操作符符合整数的条件表达式测试示例

    [root@adminset 06]# m=21;n=38
    [root@adminset 06]# ((m>20&&n>30)) && echo 1 || echo 0
    1
    [root@adminset 06]# ((m>20||n>30)) && echo 1 || echo 0
    1
    [root@adminset 06]# ((m<20||n<30)) && echo 1 || echo 0
    0
    [root@adminset 06]# ((m<20 -a n<30)) && echo 1 || echo 0
    -bash: ((: m<20 -a n<30: syntax error in expression (error token is "n<30")
    0
    #内部用-a或-o也会报语法错误

    范例:使用多个[]号,并通过与或非进行混合测试

    [root@adminset 06]# m=21;n=38
    [root@adminset 06]# [ $m =gt 20 -a $n -lt 30 ] && echo 1 || echo 0
    -bash: [: too many arguments
    0
    [root@adminset 06]# [ $m gt 20 -a $n -lt 30 ] && echo 1 || echo 0
    -bash: [: too many arguments
    0
    [root@adminset 06]# [ $m -gt 20 -a $n -lt 30 ] && echo 1 || echo 0
    0
    [root@adminset 06]# [ $m -gt 20 ] || [ $n -lt 30 ] echo 1 || echo 0
    [root@adminset 06]# [ $m -gt 20 ] || [ $n -lt 30 ] && echo 1 || echo 0
    1
    
    #多个[]号之间用&&或||链接

    范例:NFS系统启动脚本中有关[]与或非判断的使用案例

    [root@adminset~]#egrep -wn "-a|-o" /etc/init.d/nfs
    75:	if [ -n "$LOCKD_TCPPORT" -o -n "$LOCKD_UDPPORT" ]; then
    87:	[ "$NFSD_MODULE" != "noload" -a -x /sbin/modprobe ] && {
    102:	if [ -n "$RQUOTAD" -a "$RQUOTAD" != "no" ]; then
    170:	if [ -n "$RQUOTAD" -a "$RQUOTAD" != "no" ]; then
    209:	if [ -n "$RQUOTAD" -a "$RQUOTAD" != "no" ]; then
    229:	if [ $MOUNTD = 1 -o $NFSD = 1 ] ; then

    范例:系统启动脚本中有关[[]]的用法和与或非的使用案例

    在操作系统中,[[]]的用法不是很多,并且大多数情况都用于通配符匹配的场景,这里不的不通过大海捞针的
    方法(遍历/etc/init.d/下的所有脚本)来帮助大家查找[[]]的用法:

    [root@69 ~]# for n in `ls /etc/init.d/*`;do egrep -wn "[[ " $n&&echo $n;done
    119:	if [[ "$dst" == /dev/mapper* ]] 
    /etc/init.d/halt
    68:	if [[ $? = 0 ]]; then
    /etc/init.d/httpd
    641:	if [[ -n "$_target" ]]; then
    656:	if [[ "$_rmnt" == "$_mnt" ]] || ! is_dump_target_configured; then
    /etc/init.d/kdump
    50:	if [[ $route == *" via "* ]] ; then
    75:	if ! [[ "$SYSLOGADDR" =~ $IPv4_regex ]] && ! [[ "$SYSLOGADDR" =~ $IPv6_regex ]];then
    80:	if [[ $? -eq 2 ]]; then
    84:	if [[ $? -ne 0 ]]; then
    /etc/init.d/netconsole
    167:	if [[ "$rootfs" == nfs* || "$rootopts" =~ _r?netdev ]] ; then
    /etc/init.d/network

    提示:可见[]中使用-a或-o更常见,[[]]中使用&&或||不常见,使用&&或||链接两个[]的多表达式判断也不常见

  • 相关阅读:
    PosegreSQL基础回顾(第 5 章 数据定义)
    PosegreSQL基础回顾(第 4 章 SQL语法)
    大数据学习2(伪分布式搭建)
    大数据学习2(MapReduce)
    大数据学习1(HDFS)
    Linux find用法
    shell循环
    查询一次数据库给多个变量赋值
    linux cut用法
    linux权限
  • 原文地址:https://www.cnblogs.com/luoahong/p/9215074.html
Copyright © 2011-2022 走看看