shell编程 - 条件测试

文章目录

  • [1. 基本概述](#1. 基本概述)
  • [2. test命令](#2. test命令)
    • [2.1 基本语法](#2.1 基本语法)
    • [2.2 实际应用](#2.2 实际应用)
    • [2.3 特点说明](#2.3 特点说明)
  • [3. 单括号 [ ]](#3. 单括号 [ ])
    • [3.1 基本语法](#3.1 基本语法)
    • [3.2 实际应用](#3.2 实际应用)
    • [3.3 重要注意事项](#3.3 重要注意事项)
  • [4. 双括号 [[ ]]](#4. 双括号 [[ ]])
    • [4.1 基本语法](#4.1 基本语法)
    • [4.2 优势特性](#4.2 优势特性)
    • [4.3 实际应用](#4.3 实际应用)
  • [5. 双括号 (( ))](#5. 双括号 (( )))
    • [5.1 基本语法](#5.1 基本语法)
    • [5.2 算术比较运算符表](#5.2 算术比较运算符表)
    • [5.3 实际应用](#5.3 实际应用)
  • [6. 数值比较详解](#6. 数值比较详解)
    • [6.1 比较运算符对照表](#6.1 比较运算符对照表)
    • [6.2 实际代码示例](#6.2 实际代码示例)
  • [7. 字符串比较详解](#7. 字符串比较详解)
    • [7.1 字符串操作符对照表](#7.1 字符串操作符对照表)
    • [7.2 实际应用](#7.2 实际应用)
  • [8. 文件测试详解](#8. 文件测试详解)
    • [8.1 文件测试操作符大全](#8.1 文件测试操作符大全)
    • [8.2 实际应用场景](#8.2 实际应用场景)
  • [9. 逻辑操作符组合](#9. 逻辑操作符组合)
    • [9.1 逻辑操作符对照表](#9.1 逻辑操作符对照表)
    • [9.2 组合使用示例](#9.2 组合使用示例)

1. 基本概述

Shell条件测试
test命令
单括号[ ]
双括号[[ ]]
双括号(( ))
可移植性好

但功能有限
test的语法糖

需要空格
Bash/Ksh扩展

功能强大
算术运算专用

适合数值比较

2. test命令

2.1 基本语法

bash 复制代码
test expression

2.2 实际应用

bash 复制代码
#!/bin/bash
file="/etc/passwd"

if test -f "$file"; then
    echo "文件 $file 存在"
fi

# 检查变量是否为空
if test -z "$USER"; then
    echo "USER变量为空"
fi

2.3 特点说明

  • 最古老的测试方式,所有POSIX兼容shell都支持
  • 返回值:条件为真返回0,为假返回1
  • 可移植性最佳,但功能相对有限

3. 单括号 [ ]

test命令的语法糖

3.1 基本语法

bash 复制代码
[ expression ]# 注意:括号内侧必须有空格

3.2 实际应用

bash 复制代码
#!/bin/bash
count=10name="Alice"

# 数值比较
if [ $count -gt 5 ]; then
    echo "count大于5"
fi

# 字符串比较
if [ "$name" = "Alice" ]; then
    echo "姓名是Alice"
fi

# 文件测试
if [ -f "/etc/hosts" ]; then
    echo "hosts文件存在"
fi

# 组合条件
if [ $count -ge 10 ] && [ "$name" != "Bob" ]; then
    echo "条件满足"
fi

3.3 重要注意事项

bash 复制代码
# ❌ 错误:缺少空格
[$count -gt 5]  # 会报错

# ✅ 正确:有空格
[ $count -gt 5 ]

# ❌ 变量未加引号(如果变量为空会出错)
[ $var = "value" ]

# ✅ 变量加引号(安全)
[ "$var" = "value" ]

4. 双括号 [[ ]]

Bash/Ksh增强测试

4.1 基本语法

bash 复制代码
[[ expression ]]

4.2 优势特性

特性 [[ ]] [ ]
模式匹配 ✅ 支持 ❌ 不支持
正则匹配 ✅ 支持 ❌ 不支持
逻辑操作符 &&, || -a, -o
字符串比较 ==, != =, !=
变量引号 可选 必需
词分割 不进行 进行

4.3 实际应用

bash 复制代码
#!/bin/bash
filename="test.log"
pattern="*.log"
number="123"
path="/usr/local/bin"

# 1. 模式匹配
if [[ "$filename" == *.log ]]; then
    echo "这是一个日志文件"
fi

# 2. 正则表达式匹配
if [[ "$number" =~ ^[0-9]+$ ]]; then
    echo "这是纯数字"
fi

# 3. 字符串比较(更直观)
if [[ $name == "Alice" ]]; then
    echo "Hello Alice"
fi

# 4. 逻辑运算符(更直观)
if [[ -f "$file" && -r "$file" ]]; then
    echo "文件存在且可读"
fi

# 5. 路径名扩展检查
if [[ -d "$path" ]]; then
    echo "$path 是一个目录"
fi

# 6. 空变量检查(无需引号)
empty_var=""
if [[ -z $empty_var ]]; then
    echo "变量为空"
fi

5. 双括号 (( ))

5.1 基本语法

bash 复制代码
(( arithmetic_expression ))
# 当算术比较的结果非0时返回真(0),结果为0时返回假(1)

5.2 算术比较运算符表

运算符 描述 示例
== 等于 (( a == b ))
!= 不等于 (( a != b ))
< 小于 (( a < b ))
> 大于 (( a > b ))
<= 小于等于 (( a <= b ))
>= 大于等于 (( a >= b ))
&& 逻辑与 (( a > 0 && b < 10 ))
|| 逻辑或 (( a == 0 || b == 0 ))
! 逻辑非 (( ! (a == b) ))

5.3 实际应用

bash 复制代码
#!/bin/bash
a=10
b=20
c=0

# 1. 简单比较
if (( a < b )); then
    echo "a小于b"
fi

# 2. 算术运算
if (( a * 2 > b )); then
    echo "a的两倍大于b"
fi

# 3. 自增自减
counter=0
while (( counter < 5 )); do
    echo "计数: $counter"
    (( counter++ ))  # 自增
done

# 4. 复杂表达式
if (( (a + b) > 25 && a % 2 == 0 )); then
    echo "条件满足"
fi

# 5. 三元运算风格
(( max = a > b ? a : b ))
echo "最大值是: $max"

# 6. 位运算
flags=5  # 二进制 0101
if (( (flags & 1) == 1 )); then
    echo "最低位是1"
fi

6. 数值比较详解

6.1 比较运算符对照表

数值比较
test/[ ]用法
(( ))用法
-eq 等于
-ne 不等于
-gt 大于
-lt 小于
-ge 大于等于
-le 小于等于
== 等于
!= 不等于
> 大于 < 小于
>= 大于等于 <= 小于等于

6.2 实际代码示例

bash 复制代码
#!/bin/bash
num1=10
num2=20

echo "使用test/[ ]:"
if [ $num1 -lt $num2 ]; then
    echo "$num1 小于 $num2"
fi

echo -e "\n使用(( )):"
if (( num1 < num2 )); then
    echo "$num1 小于 $num2"
fi

# 浮点数比较(需要bc命令)
float1=3.14
float2=2.71
if [ $(echo "$float1 > $float2" | bc) -eq 1 ]; then
    echo "$float1 大于 $float2"
fi

7. 字符串比较详解

7.1 字符串操作符对照表

操作符 test/[ ] [[ ]] 说明
等于 = 或 == = 或 == [[ ]]中==是标准
不等于 != !=
小于 < (需转义) < 按字典序比较
大于 > (需转义) > 按字典序比较
空检查 -z -z 字符串长度为0
非空检查 -n -n 字符串长度不为0

7.2 实际应用

bash 复制代码
#!/bin/bash
str1="hello"
str2="world"
str3=""
str4="HELLO"

# 1. 基本比较
if [ "$str1" = "hello" ]; then
    echo "字符串相等"
fi

# 2. 字典序比较
if [[ "$str1" < "$str2" ]]; then
    echo "'$str1' 在 '$str2' 之前"
fi

# 3. 空值检查
if [ -z "$str3" ]; then
    echo "str3是空字符串"
fi

if [ -n "$str1" ]; then
    echo "str1不是空字符串"
fi

# 4. 大小写敏感比较
if [[ "$str1" == "hello" ]]; then
    echo "精确匹配"
fi

# 5. 大小写不敏感比较(Bash 4+)
if [[ "${str1,,}" == "${str4,,}" ]]; then
    echo "忽略大小写匹配"
fi

# 6. 包含关系检查
if [[ "$str1" == *"ell"* ]]; then
    echo "包含子串'ell'"
fi

# 7. 前缀/后缀检查
if [[ "$str1" == "hel"* ]]; then
    echo "以'hel'开头"
fi

if [[ "$str1" == *"lo" ]]; then
    echo "以'lo'结尾"
fi

8. 文件测试详解

8.1 文件测试操作符大全

操作符 描述 示例
-e 文件/目录是否存在 [ -e file ]
-f 是否为普通文件 [ -f file ]
-d 是否为目录 [ -d dir ]
-L 是否为符号链接 [ -L link ]
-r 是否可读 [ -r file ]
-w 是否可写 [ -w file ]
-x 是否可执行 [ -x file ]
-s 文件大小是否>0 [ -s file ]
-O 文件所有者是否为当前用户 [ -O file ]
-G 文件所属组是否为当前用户组 [ -G file ]
-N 文件自上次读取后是否被修改 [ -N file ]
file1 -nt file2 file1是否比file2新 [ file1 -nt file2 ]
file1 -ot file2 file1是否比file2旧 [ file1 -ot file2 ]
file1 -ef file2 是否相同文件(硬链接) [ file1 -ef file2 ]

8.2 实际应用场景

bash 复制代码
#!/bin/bash
file="/etc/passwd"
dir="/tmp"
link="/usr/bin/python"

# 1. 检查文件存在性
if [[ -e "$file" ]]; then
    echo "$file 存在"
fi

# 2. 检查文件类型
if [[ -f "$file" ]]; then
    echo "$file 是普通文件"
fi

if [[ -d "$dir" ]]; then
    echo "$dir 是目录"
fi

if [[ -L "$link" ]]; then
    echo "$link 是符号链接"
fi

# 3. 检查权限
if [[ -r "$file" ]]; then
    echo "$file 可读"
fi

if [[ -w "$file" ]]; then
    echo "$file 可写"
fi

# 4. 检查文件新旧
log1="/var/log/syslog"
log2="/var/log/auth.log"

if [[ "$log1" -nt "$log2" ]]; then
    echo "$log1 比 $log2 新"
fi

# 5. 复合文件检查
backup_file="/backup/data.tar.gz"
if [[ -f "$backup_file" && -s "$backup_file" ]]; then
    echo "备份文件存在且非空"
    if [[ -r "$backup_file" && -O "$backup_file" ]]; then
        echo "并且可读且属于当前用户"
    fi
fi

# 6. 检查特殊文件
socket="/var/run/docker.sock"
if [[ -S "$socket" ]]; then
    echo "$socket 是socket文件"
fi

named_pipe="/tmp/myfifo"
if [[ -p "$named_pipe" ]]; then
    echo "$named_pipe 是命名管道"
fi

9. 逻辑操作符组合

9.1 逻辑操作符对照表

逻辑 test/[ ] [[ ]] (( )) 说明
-a && && 所有条件为真
-o || || 任一条件为真
! ! ! 条件取反
分组 ( ) ( ) ( ) 改变优先级

9.2 组合使用示例

bash 复制代码
#!/bin/bash
age=25
name="John"
file="/tmp/test.txt"

# 1. 基本逻辑组合
# 使用test/[ ]
if [ "$age" -gt 18 -a "$name" = "John" ]; then
    echo "John成年了"
fi

# 使用[[ ]]
if [[ $age -gt 18 && $name == "John" ]]; then
    echo "John成年了"
fi

# 2. 复杂逻辑组合
score=85
attendance=90

if [[ ($score -ge 60 && $attendance -ge 80) || $score -ge 90 ]]; then
    echo "考试通过"
fi

# 3. 使用括号改变优先级
if [[ $age -gt 18 && ($name == "John" || $name == "Jane") ]]; then
    echo "成年人John或Jane"
fi

# 4. 文件检查组合
if [[ -f "$file" && ( -r "$file" || -w "$file" ) ]]; then
    echo "文件存在且可读或可写"
fi

# 5. 逻辑非的应用
if [[ ! -d "/nonexistent" ]]; then
    echo "目录不存在"
fi

if [[ ! ( $age -lt 18 && $name == "Child" ) ]]; then
    echo "不是小孩Child"
fi
相关推荐
2301_772204282 小时前
Linux 驱动开发:杂项设备驱动与自动设备号管理
linux·运维·驱动开发
黄昏晓x2 小时前
Linux----缓冲区
linux·运维·服务器
2501_901147832 小时前
学习笔记:单调递增数字求解的迭代优化与工程实践
linux·服务器·笔记·学习·算法
似霰2 小时前
Linux timerfd 的基本使用
android·linux·c++
寄存器漫游者2 小时前
Linux 软件编程 命令、内核与 Shell
linux·运维·服务器
qinyia3 小时前
通过本地构建解决Cartographer编译中absl依赖缺失问题
linux·运维·服务器·mysql·ubuntu
郝亚军3 小时前
ubuntu启一个udp server,由一个client访问
linux·ubuntu·udp
苦逼IT运维3 小时前
从 0 到 1 理解 Kubernetes:一次“破坏式”学习实践(一)
linux·学习·docker·容器·kubernetes
李小白202002023 小时前
EMMC写入/烧录逻辑
linux·运维·服务器