首页  /  Linux 进阶  /  正文

系统脚本里的条件测试与逻辑脚本

Linux 进阶 2026-10-02📖 18 分钟👁 —
🐚 Linux 进阶 · Shell 编程第 6 / 10 页12345678910📖 完整导航 →

一、读系统脚本,学条件测试的写法

1. 如何阅读优秀的脚本

变量测试必须加引号:

ubuntu@VM-0-9-ubuntu:~/shell$ file1=jitaimei.jpg 
ubuntu@VM-0-9-ubuntu:~/shell$ [ -f "$file1" ] && echo "我是两年半练习生" || echo "我是好人"
我是两年半练习生

想要学好 shell 编程,能够解决日常工作的程度,想进阶到高阶 shell 开发,必然要看优秀脚本:

# 截取了一段linux系统脚本
root@VM-0-9-ubuntu:/etc/init.d# cat ssh
#! /bin/sh

### BEGIN INIT INFO
# Provides:		ssh sshd
# Required-Start:	$remote_fs $syslog
# Required-Stop:	$remote_fs $syslog
# Default-Start:	2 3 4 5
# Default-Stop:		
# Short-Description:	OpenBSD Secure Shell server
### END INIT INFO

set -e

# /etc/init.d/ssh: start and stop the OpenBSD "secure shell(tm)" daemon

test -x /usr/sbin/sshd || exit 0
( /usr/sbin/sshd -\? 2>&1 | grep -q OpenSSH ) 2>/dev/null || exit 0

umask 022

if test -f /etc/default/ssh; then
    . /etc/default/ssh
fi

. /lib/lsb/init-functions

if [ -n "$2" ]; then
    SSHD_OPTS="$SSHD_OPTS $2"
fi

centos 的 network 脚本也是这个套路:先 . /etc/init.d/functions 把函数库加载进来,再用 [ ! -f ... ]、[ "${NETWORKING}" = "no" ] && exit 6 做前置检查。

CentOS 的 /etc/init.d/network:source 函数库之后,一串 [] 做条件判断,中间还有 CWD=$(pwd) 和 cd /etc/sysconfig/network-scripts

2. 字符串值判断逻辑

常用字符串测试操作符:-n 非空为真、-z 空为真、串1 = 串2、串1 != 串2 的说明

= 判断是否相等,! 取反,!= 不等于。

mysql 自带的脚本用到了这些符号:

su_kill() {
    if test "$USER" = "$user"; then
    # 如果两个值相等,杀掉进程日志扔掉
        kill $* >/dev/null 2>&1
    else
        su - $user -s /bin/sh -c "kill $*" >/dev/null 2>&1
    fi
}

注意:

# 求字符串是否相等
ubuntu@VM-0-9-ubuntu:~/shell$ [ "yuchao" = "chaochao" ] && echo ok || echo no
no

ubuntu@VM-0-9-ubuntu:~/shell$ name=yuchao
ubuntu@VM-0-9-ubuntu:~/shell$ echo $name
yuchao
ubuntu@VM-0-9-ubuntu:~/shell$ [ "$name" = "yuchao" ] && echo ok || echo no
ok
ubuntu@VM-0-9-ubuntu:~/shell$ [ "$name" = "yuchaooo" ] && echo ok || echo no
no

ubuntu@VM-0-9-ubuntu:~/shell$ [ "$name" != "yuchaooo" ] && echo ok || echo no
ok
# ! -f 对结果取反
ubuntu@VM-0-9-ubuntu:~/shell$ [ -f "ccll.txt" ] && echo ok || echo no
no
ubuntu@VM-0-9-ubuntu:~/shell$ [ ! -f "ccll.txt" ] && echo ok || echo no
ok

3. 数值比较符号

数值比较符号对照:[] 和 test 里用 -eq -ne -gt -ge -lt -le,(( )) 和 [[]] 里可以直接用 == != > >= < <=

用数学符号

# 这个结果是错的
ubuntu@VM-0-9-ubuntu:~/shell$ [ 0 > 1 ] && echo ok || echo no
ok
ubuntu@VM-0-9-ubuntu:~/shell$ [ 0 \> 1 ] && echo ok || echo no
no

ubuntu@VM-0-9-ubuntu:~/shell$ [ 1 != 1 ] && echo ok || echo no
no
ubuntu@VM-0-9-ubuntu:~/shell$ [ 1 != 3 ] && echo ok || echo no
ok

中括号使用数学比较符号要添加转义符号 \,!= 不用加。

用字符符号

# 大于 -gt
ubuntu@VM-0-9-ubuntu:~/shell$ [ 2 -gt 13 ] && echo ok || echo no
no
ubuntu@VM-0-9-ubuntu:~/shell$ [ 2 -gt 1 ] && echo ok || echo no
ok

test 和中括号变量加引号的原因

ubuntu@VM-0-9-ubuntu:~/shell$ n1=98;n2=99
ubuntu@VM-0-9-ubuntu:~/shell$ test "$n1" -eq "$n2" && echo yes || echo no
no

ubuntu@VM-0-9-ubuntu:~/shell$ test "$n1" -lt "$n2" && echo yes || echo no
yes
# test支持字符和数学符号不用转义
ubuntu@VM-0-9-ubuntu:~/shell$ test "$n1" != "$n2" && echo yes || echo no
yes
ubuntu@VM-0-9-ubuntu:~/shell$ test "$n1" = "$n2" && echo yes || echo no
no

test 和 [] 语法都支持字符和数学符号,中括号需要转义。

双中括号

对单中括号的补充,可以使用正则表达式,不需要转义符号,自动识别数学符号。

实际使用最多的是单中括号:

# 符号和字符都支持
ubuntu@VM-0-9-ubuntu:~/shell$ [[ 5 = 6 ]] && echo ok || echo no
no
ubuntu@VM-0-9-ubuntu:~/shell$ [[ 5 -eq 6 ]] && echo ok || echo no
no

系统自带的脚本也用了很多条件测试。

4. 逻辑运算符号

对应参数

&& 和 -a,|| 和 -o。

and 是递进,左边为真执行右边;or 是左边为假执行右边,左边为真直接跳过右边。

中括号逻辑运算比较

# 也可以写目录路径
ubuntu@VM-0-9-ubuntu:~/shell$ file1=calculation.sh
ubuntu@VM-0-9-ubuntu:~/shell$ file2=calculation2.sh
ubuntu@VM-0-9-ubuntu:~/shell$ [ -f "$file1" -a -f "$file2" ] && echo yes || echo no
yes

ubuntu@VM-0-9-ubuntu:~/shell$ [ -f "$file1" -o -f "$f2" ] && echo yes || echo no
yes

ubuntu@VM-0-9-ubuntu:~/shell$ [ -f "$file1" || -f "$f2" ] && echo yes || echo no
-bash: [: missing `]'
-f: command not found

中括号的逻辑判断无法使用 && 和 ||,只能使用字符参数。

双中括号逻辑运算比较

# -n 判断字符长度是否为0,非空为真
ubuntu@VM-0-9-ubuntu:~/shell$ a=""
ubuntu@VM-0-9-ubuntu:~/shell$ b="yuyu"
ubuntu@VM-0-9-ubuntu:~/shell$ test -n "$a" && echo yes || echo no
no

ubuntu@VM-0-9-ubuntu:~/shell$ [[ -n "$a" && "$a" = "$b" ]] && echo yes || echo no
no

# 使结果为真
# 改 a 后条件取反
ubuntu@VM-0-9-ubuntu:~/shell$ a=cc
ubuntu@VM-0-9-ubuntu:~/shell$ [[ -n "$a" && ! "$a" = "$b" ]] && echo yes || echo no
yes
# a 有值,后条件改为 !=(此处省略)
# a 改为b的值(此处省略)

二、逻辑运算脚本

1. 判断用户输入

脚本根据需求开发,需求:接收用户输入,判断是否等于某个数字。

ubuntu@VM-0-9-ubuntu:~/shell$ cat test_and_or.sh 
#!/bin/bash

read -p "输入一个字符" var1

# 逻辑测试
[ "$var1" -eq "1" ] && {
	echo $var1
	exit 0

}

[ "$var1" = "2" ] && {
	echo $var1
	exit 0

}

# 限制只能输入1或2否则错误

[ "$var1" != "2" -a "$var1" != "1" ] && {
	echo "发生错误,必须输入1或2"
	exit 1

}


ubuntu@VM-0-9-ubuntu:~/shell$ bash test_and_or.sh 
输入一个字符q
test_and_or.sh: line 6: [: q: integer expression expected
发生错误,必须输入1或2
ubuntu@VM-0-9-ubuntu:~/shell$ bash test_and_or.sh 
输入一个字符2
2

可以使用 vim 写代码,也可以写完了粘贴到 vim 中。

2. lamp / lnmp 安装脚本

需求:安装 lnmp/lamp 脚本开发。模拟创建两个安装脚本 lnmp.sh、lamp.sh。

为了减少 bug,找到原始安装脚本,然后根据选择安装其中一个。

开发脚本一定会有真和假的两种情况,优先处理错误的逻辑情况,因为错误的逻辑情况最好处理。

[[ $num =~ [1-3] ]] 其中 =~ 表示使用正则,表示 num 变量必须为 1-3 之间的:

root@VM-0-9-ubuntu:~/shell/test_scripts# cat lamp_and_lnmp.sh
#!/bin/bash

# 判断脚本目录是否存在
# 不要覆盖系统的大写PATH变量
#
path=/root/shell/test_scripts

[ ! -d "$path" ] && mkdir $path -p

# 脚本正常逻辑

cat <<END
    1.[install lamp]
    2.[install lnmp]
    3.[exit]
    Please input the num you want:

END

read num

# 根据num变量进行逻辑处理

# 限制num输入为数字
expr $num + 1 &> /dev/null # 不是数字就会报错
# 判断上个结果,不为0就错
[ $? -ne 0 ] && {
	echo "输入必须为 1|2|3|"
	exit 1
}

# 对输入的数字判断1,2,3

[ "$num" -eq "1" ] && {
	echo "开始安装lamp...waiting..."
# 这里的是伪代码 生产环境写安装代码
#
# 对文件权限判断是否可执行
	[ -x "$path/lamp.sh" ] || {
		echo "文件没有执行权限"
		exit 1
	}
	source $path/lamp.sh
	exit $?
}



[ "$num" -eq "2" ] && {
        echo "开始安装lnmp...waiting..."
        [ -x "$path/lnmp.sh" ] || {
                echo "文件没有执行权限"
                exit 2
        }
        source $path/lnmp.sh
        exit $?
}

[ "$num" -eq "3" ] && {
	echo "bye~"
	exit 3
}
# 下面和if的用法一样,只是重复写了脚本,二选一就行
# 限制用户必须输入1,2,3
# 支持正则的[[]]
# 输入不为1-3时
[[ ! "$num" =~ [1-3] ]] && {
	echo "输入的数字必须为1-3之间"
	exit 4
}

执行效果:

root@VM-0-9-ubuntu:~/shell/test_scripts# bash lamp_and_lnmp.sh
    1.[install lamp]
    2.[install lnmp]
    3.[exit]
    Please input the num you want:

1
开始安装lamp...waiting...
lamp is installed
root@VM-0-9-ubuntu:~/shell/test_scripts# bash lamp_and_lnmp.sh
    1.[install lamp]
    2.[install lnmp]
    3.[exit]
    Please input the num you want:

2
开始安装lnmp...waiting...
lnmp is installed
root@VM-0-9-ubuntu:~/shell/test_scripts# bash lamp_and_lnmp.sh
    1.[install lamp]
    2.[install lnmp]
    3.[exit]
    Please input the num you want:

3
bye~

补充内容(如图)

四种测试写法的对照表:边界要不要空格、逻辑操作符、整数和字符串比较操作符、是否支持通配符匹配

最常用的是中括号搭配字符型参数。

至此 shell 进阶篇结束。

可喜可贺,めでたし めでたし

写脚本的直觉基本就来自这一页:先看系统自带的 /etc/init.d 脚本怎么用 test 和 [] 做前置检查, 再记住“能用 [[ ]] 就用 [[ ]]、变量一定加引号、&& 和 -a 别混着写”, 最后按“先处理错误分支、再处理正常分支”的顺序把逻辑铺出来,脚本就不会太乱。