Linux Shell编程之二选择结构

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/下的文件名也要随之而变;

[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语句结合函数来实现。

# 一般情况下,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是要踢掉的参数个数

[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选项;

#!/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		

你可能感兴趣的:(shell编程;选择)