条件判断

条件比较

test

test 命令用于检查文件类型并比较值。测试用于条件执行中。它用于:

  • 文件属性比较
  • 执行字符串比较。
  • 基本算术比较。
$ test condition
$ test condition && true-command
$ test condition || false-command
$ test condition && true-command || false-command

很多时候我们可以不用 test 关键字而是直接使用 [ ] 来包含条件语句,在 Shell 提示符下键入以下命令(5 是否大于 2?):

test 5 -eq 5 && echo Yes || echo No
test 5 -eq 15 && echo Yes || echo No
test 5 -ne 10 && echo Yes || echo No
test -f /etc/resolv.conf && echo "File /etc/resolv.conf found." || echo "File /etc/resolv.conf not found."
test -f /etc/resolv1.conf && echo "File /etc/resolv1.conf found." || echo "File /etc/resolv1.conf not found."

一个简单的 shell 脚本来查找用户名(finduser.sh)

# set var
PASSWD_FILE=/etc/passwd

# get user name
read -p "Enter a user name : " username

# try to locate username in in /etc/passwd
grep "^$username" $PASSWD_FILE > /dev/null

# store exit status of grep
# if found grep will return 0 exit stauts
# if not found, grep will return a nonzero exit stauts
status=$?

if test $status -eq 0
then
	echo "User '$username' found in $PASSWD_FILE file."
else
	echo "User '$username' not found in $PASSWD_FILE file."
fi

字符串判断

[ -z STRING ] 如果STRING的长度为零则返回为真,即空是真
[ -n STRING ] 如果STRING的长度非零则返回为真,即非空是真
[ STRING1 ]  如果字符串不为空则返回为真,与-n类似
[ STRING1 == STRING2 ] 如果两个字符串相同则返回为真
[ STRING1 != STRING2 ] 如果字符串不相同则返回为真
[ STRING1 < STRING2 ] 如果 “STRING1”字典排序在“STRING2”前面则返回为真。
[ STRING1 > STRING2 ] 如果 “STRING1”字典排序在“STRING2”后面则返回为真。

# 正则表达式
doiido="hero"
if  [[ "$doiido" == h* ]];then
    echo "hello,hero"
fi

数值判断

[ INT1 -eq INT2 ] INT1和INT2两数相等返回为真 ,=
[ INT1 -ne INT2 ] INT1和INT2两数不等返回为真 ,<>
[ INT1 -gt INT2 ] INT1大于INT2返回为真 ,>
[ INT1 -ge INT2 ] INT1大于等于INT2返回为真,>=
[ INT1 -lt INT2 ] INT1小于INT2返回为真 ,<
[ INT1 -le INT2 ] INT1小于等于INT2返回为真,<=

# a>b且a<c
(( a > b )) && (( a < c ))
[[ $a > $b ]] && [[ $a < $c ]]
[ $a -gt $b -a $a -lt $c ]

# a>b或a<c
(( a > b )) || (( a < c ))
[[ $a > $b ]] || [[ $a < $c ]]
[ $a -gt $b -o $a -lt $c ]

逻辑判断

[ ! EXPR ] 逻辑非,如果 EXPR 是false则返回为真。
[ EXPR1 -a EXPR2 ] 逻辑与,如果 EXPR1 and EXPR2 全真则返回为真。
[ EXPR1 -o EXPR2 ] 逻辑或,如果 EXPR1 或者 EXPR2 为真则返回为真。
[ ] || [ ] 用OR来合并两个条件
[ ] && [ ] 用AND来合并两个条件
[ -t FD ] 如果文件描述符 FD(默认值为1)打开且指向一个终端则返回为真
[ -o optionname ] 如果shell选项optionname开启则返回为真

文件/目录判断

# 常用的:
[ -a FILE ] 如果 FILE 存在则为真。
[ -d FILE ] 如果 FILE 存在且是一个目录则返回为真。
[ -e FILE ] 如果 指定的文件或目录存在时返回为真。
[ -f FILE ] 如果 FILE 存在且是一个普通文件则返回为真。
[ -r FILE ] 如果 FILE 存在且是可读的则返回为真。
[ -w FILE ] 如果 FILE 存在且是可写的则返回为真。(一个目录为了它的内容被访问必然是可执行的)
[ -x FILE ] 如果 FILE 存在且是可执行的则返回为真。

# 不常用的:
[ -b FILE ] 如果 FILE 存在且是一个块文件则返回为真。
[ -c FILE ] 如果 FILE 存在且是一个字符文件则返回为真。
[ -g FILE ] 如果 FILE 存在且设置了SGID则返回为真。
[ -h FILE ] 如果 FILE 存在且是一个符号符号链接文件则返回为真。(该选项在一些老系统上无效)
[ -k FILE ] 如果 FILE 存在且已经设置了冒险位则返回为真。
[ -p FILE ] 如果 FILE 存并且是命令管道时返回为真。
[ -s FILE ] 如果 FILE 存在且大小非0时为真则返回为真。
[ -u FILE ] 如果 FILE 存在且设置了SUID位时返回为真。
[ -O FILE ] 如果 FILE 存在且属有效用户ID则返回为真。
[ -G FILE ] 如果 FILE 存在且默认组为当前组则返回为真。(只检查系统默认组)
[ -L FILE ] 如果 FILE 存在且是一个符号连接则返回为真。
[ -N FILE ] 如果 FILE 存在 and has been mod如果ied since it was last read则返回为真。
[ -S FILE ] 如果 FILE 存在且是一个套接字则返回为真。
[ FILE1 -nt FILE2 ] 如果 FILE1 比 FILE2 新, 或者 FILE1 存在但是 FILE2 不存在则返回为真。
[ FILE1 -ot FILE2 ] 如果 FILE1 比 FILE2 老, 或者 FILE2 存在但是 FILE1 不存在则返回为真。
[ FILE1 -ef FILE2 ] 如果 FILE1 和 FILE2 指向相同的设备和节点号则返回为真。

if 条件判断

Bash Shell 会按顺序执行 if 语句,如果 command 执行后且它的返回状态是 0,则会执行符合该条件执行的语句,否则后面的命令不执行,跳到下一条命令。当有多个嵌套时,只有第一个返回 0 退出状态的命令会导致符合该条件执行的语句部分被执行,如果所有的语句的执行状态都不为 0,则执行 else 中语句。返回状态是最后一个命令的退出状态,或者当没有条件是真的话为 0。

if command
then
    command executed successfully
    execute all commands up to else statement
    or to fi if there is no else statement

else
    command failed so
    execute all commands up to fi
fi


# 使用 test 进行判断
if test var -eq val
then
    command executed successfully
    execute all commands up to else statement
    or to fi if there is no else statement

else
    if command failed then
    execute all commands up to fi
fi

if test var == value
then
     command1
     command2
     ...
     commandN
fi

# 基本语法
if [ command ]; then
     符合该条件执行的语句
fi

# 扩展语法
if [ command ];then
     符合该条件执行的语句
elif [ command ];then
     符合该条件执行的语句
else
     符合该条件执行的语句
fi

注意,[ ] 表示条件测试。注意这里的空格很重要。要注意在 [ 后面和 ] 前面都必须要有空格。在 Shell 中,then 和 fi 是分开的语句。如果要在同一行里面输入,则需要用分号将他们隔开。我们也可以多层嵌套条件判断:

if condition
then
    if condition
    then
        .....
        ..
        do this
    else
        ....
        ..
        do this
    fi
else
    ...
    .....
    do this
fi

字符串判断

# 两个变量判断是否相等
if [ "$var1" = "$var2" ]; then
  echo '$var1 eq $var2'
else
  echo '$var1 not eq $var2'
fi

# 是判断变量$doiido是否有值
if [ ! -n "$doiido" ]; then
  echo "$doiido is empty"
  exit 0
fi

# 数值的比较
if [ "$num" -gt "150" ];then
   echo "$num is biger than 150"
fi

文件判断

# 判断目录 $doiido 是否存在,若不存在,则新建一个
if [ ! -d "$doiido"]; then
  mkdir "$doiido"
fi

# 判断普通文件 $doiido 是否存,若不存在,则新建一个
if [ ! -f "$doiido" ]; then
  touch "$doiido"
fi

# 判断 $doiido 是否存在并且是否具有可执行权限
if [ ! -x "$doiido"]; then
  mkdir "$doiido"
chmod +x "$doiido"
fi

这是使用逻辑 not 的示例脚本 ! 快速制作备份目录:

#!/bin/bash
# A sample shell script to backup MySQL database

# Get todays date
NOW=$(date +"%d-%m-%Y")

# Location to store mysql backup
BAK="/nas10/.mysql-database"

# MySQL Server Login Information
MUSER="root"			#### mysql user name ###
MPASS="YOUR-PASSWORD-HERE"	#### mysql password  ###
MHOST="127.0.0.1"		#### mysql host name ###

# Full path to common utilities
MYSQL="/usr/bin/mysql"
MYSQLDUMP="/usr/bin/mysqldump"
GZIP="/bin/gzip"

# If backup directory does not exits create it using logical not
if [ ! -d "$BAK" ]
then
  mkdir -p "$BAK"
fi

# Get all mysql databases names
DBS="$($MYSQL -u $MUSER -h $MHOST -p$MPASS -Bse 'show databases')"

# Start backup
echo -n "Dumping..."

# Use the for loop
for db in $DBS
do
 FILE="$BAK/mysql-$db.$NOW-$(date +"%T").gz"
  $MYSQLDUMP -u $MUSER -h $MHOST -p$MPASS $db | $GZIP -9 > $FILE
 echo -n "."
done
echo -n  "...Done"
echo ""

系统判断

# 测试退出状态
if [ $? -eq 0 ];then
    echo 'That is ok'
fi

# 检测执行脚本的用户
if [ "$(whoami)" != 'root' ]; then
   echo  "You  have no permission to run $0 as non-root user."
   exit  1;
fi

# 查看当前操作系统类型
SYSTEM=`uname  -s`
if [ $SYSTEM = "Linux" ] ; then
   echo "Linux"
elif
    [ $SYSTEM = "FreeBSD" ] ; then
   echo "FreeBSD"
elif
    [ $SYSTEM = "Solaris" ] ; then
    echo "Solaris"
else
    echo  "What?"
fi

# 判断 read 传入的参数
read -p "please  input a score:"  score
echo  -e "your  score [$score] is judging by sys now"
if [ "$score" -ge "0" ]&&[ "$score" -lt "60" ];then
    echo  "sorry,you  are lost!"
elif [ "$score" -ge "60" ]&&[ "$score" -lt "85" ];then
    echo "just  soso!"
elif [ "$score" -le "100" ]&&[ "$score" -ge "85" ];then
     echo "good  job!"
else
     echo "input  score is wrong, the range is [0-100]!"
fi

以下脚本(chk_hardware.sh)在运行 64 位 Linux 内核的 x86-64 计算机上使用 mcelog 命令。它将找出硬件错误(例如 RAM 或 CPU),并向服务器管理员发送电子邮件。这对于在实际服务器崩溃之前预测服务器硬件故障很有用:

#!/bin/bash
# Purpose: Detecting Hardware Errors
# Author: Vivek Gite <vivek@nixcraft.com>
# Note : The script must run as a cron-job.
# Last updated on : 28-Aug-2007
# -----------------------------------------------

# Store path to commands
LOGGER=/usr/bin/logger
FILE=/var/log/mcelog

# Store email settings
AEMAIL="vivek@nixcraft.net.in"
ASUB="H/W Error - $(hostname)"
AMESS="Warning - Hardware errors found on $(hostname) @ $(date). See log file for the details /var/log/mcelog."
OK_MESS="OK: NO Hardware Error Found."
WARN_MESS="ERROR: Hardware Error Found."


# Check if $FILE exists or not
if test ! -f "$FILE"
then
	echo "Error - $FILE not found or mcelog is not configured for 64 bit Linux systems."
	exit 1
fi

# okay search for errors in file
error_log=$(grep -c -i "hardware error" $FILE)

# error found or not?
if [ $error_log -gt 0 ]
then    # yes error(s) found, let send an email
	echo "$AMESS" | email -s "$ASUB" $AEMAIL
else    # naa, everything looks okay
	echo "$OK_MESS"
fi
下一页