Shell脚本之 “[[]]“ 详解

[[ ]] 是 Bash、Zsh 和 Ksh 等现代 Shell 提供的增强型条件测试结构,它比传统的 [ ] 更强大且更安全。下面我将全面解析 [[ ]] 的功能和用法。

基本概念

  1. [[]] 是 Shell 关键字(不是命令)
  2. 提供比 [ ] 更丰富的功能集
  3. 不会进行单词分割和路径名扩展
  4. 支持更自然的语法(如不需要引号保护变量)

基本语法

if [[ 条件表达式 ]]; then
    # 条件为真时执行的命令
fi

1. 字符串比较

操作符说明
===字符串相等
!=字符串不相等
<按字典序小于(无需转义)
>按字典序大于(无需转义)
=~正则表达式匹配(Bash 3.0+)
== (带通配符)模式匹配

示例

name="example.txt"

# 字符串相等
if [[ "$name" == "example.txt" ]]; then
    echo "文件名匹配"
fi

# 模式匹配(通配符)
if [[ "$name" == *.txt ]]; then
    echo "是文本文件"
fi

# 正则表达式匹配
if [[ "$name" =~ ^ex.*\.txt$ ]]; then
    echo "符合正则表达式"
fi

# 字典序比较
if [[ "apple" < "banana" ]]; then
    echo "apple 在 banana 之前"
fi

2. 数值比较

可以直接使用数学比较符号(不需要 -eq 等形式):

操作符说明
==等于
!=不等于
<小于
>大于
<=小于等于
>=大于等于

示例

num=10

if [[ num -eq 10 ]]; then   # 传统方式仍可用
if [[ num == 10 ]]; then    # 更直观的方式
if (( num == 10 )); then    # 算术比较的最佳方式

if [[ $num > 5 ]]; then
    echo "数字大于5"
fi

3. 文件测试

[ ] 相同的文件测试操作符:

操作符说明
-e文件存在
-f是普通文件
-d是目录
-s文件非空
-r可读
-w可写
-x可执行
-L是符号链接
-O属于当前用户
-G属于当前用户的组
-N自上次读取后被修改
file1 -nt file2file1 比 file2 新
file1 -ot file2file1 比 file2 旧

示例

file="/path/to/file"

if [[ -e "$file" ]]; then
    echo "文件存在"
fi

if [[ -f "$file" && -s "$file" ]]; then
    echo "是普通文件且非空"
fi

4. 逻辑运算符

更自然的逻辑运算符:

操作符说明
&&逻辑与
|| 逻辑或
!逻辑非

示例

if [[ -d "$dir" && -w "$dir" ]]; then
    echo "目录存在且可写"
fi

if [[ ! -f "$lockfile" ]]; then
    echo "锁文件不存在"
fi

5. 高级特性

模式匹配

name="file123.txt"

if [[ "$name" == file*.txt ]]; then
    echo "匹配 file*.txt 模式"
fi

正则表达式匹配

email="user@example.com"

if [[ "$email" =~ ^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$ ]]; then
    echo "有效的电子邮件地址"
fi

自动变量引用

不需要引号保护变量:

filename="my file.txt"

# 在 [ ] 中会出错
if [ -f $filename ]; then ...  # 错误!

# 在 [[ ]] 中安全
if [[ -f $filename ]]; then ... # 正确

6. [[ ]][ ] 的关键区别

特性[[ ]][ ]
类型Shell 关键字命令(通常是内置或外部)
单词分割不会进行会进行
路径名扩展不会进行会进行
变量引用不需要引号必须使用引号
模式匹配支持 (==, =~)不支持
逻辑运算符使用 &&, ||, !使用 -a, -o, !
字符串比较运算符==, !=, <, >=, != (需转义 <, >)
数值比较可直接用 <, >必须用 -lt, -gt
POSIX 兼容性不兼容兼容

7. 最佳实践

  1. 优先使用 [[ ]]

    • 在 Bash 脚本中优先使用 [[ ]],它更安全、功能更强大
    • 只在需要 POSIX 兼容性时使用 [ ]
  2. 变量引用

    • [[ ]] 中可以不加引号,但为了代码清晰仍建议加引号
    if [[ "$var" == value ]]; then
    
  3. 复合条件

    • 使用 &&|| 代替 -a-o
    if [[ -f "$file" && -r "$file" ]]; then
    
  4. 模式匹配

    • 使用 == 进行通配符匹配
    • 使用 =~ 进行正则匹配
  5. 数值比较

    • 对于算术比较,(( )) 通常是最佳选择
    if (( num > 10 )); then
    

8. 实际应用示例

  1. 检查命令是否成功:
if [[ $(command) == "expected output" ]]; then
    echo "命令输出符合预期"
fi
  1. 安全的文件处理:
file="some file.txt"
if [[ -e "$file" && ! -d "$file" ]]; then
    echo "文件存在且不是目录"
fi
  1. 高级字符串检查:
input="12345"
if [[ "$input" =~ ^[0-9]+$ ]]; then
    echo "输入全是数字"
fi
  1. 多条件判断:
hour=$(date +%H)
if [[ $hour -ge 8 && $hour -lt 18 ]]; then
    echo "工作时间"
elif [[ $hour -ge 18 || $hour -lt 8 ]]; then
    echo "非工作时间"
fi

总结

[[ ]] 是现代 Shell 脚本中条件测试的首选工具,它提供了:

  • 更安全的变量处理
  • 更丰富的比较功能
  • 更直观的语法
  • 更强大的模式匹配能力
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值