逻辑运算符 #

一、逻辑运算符概述 #

1.1 基本逻辑运算符 #

运算符 说明 示例
&& 逻辑与 [[ $a -gt 0 && $b -gt 0 ]]
|| 逻辑或 [[ $a -gt 0 || $b -gt 0 ]]
! 逻辑非 [[ ! $a -eq 0 ]]

1.2 命令连接符 #

运算符 说明 示例
&& 前面成功才执行后面 cmd1 && cmd2
|| 前面失败才执行后面 cmd1 || cmd2
; 顺序执行 cmd1 ; cmd2

二、逻辑与 (&&) #

2.1 条件判断中使用 #

bash
#!/bin/bash

a=10
b=5

# 在 [[ ]] 中使用
if [[ $a -gt 0 && $b -gt 0 ]]; then
    echo "a和b都大于0"
fi

# 在 (( )) 中使用
if (( a > 0 && b > 0 )); then
    echo "a和b都大于0"
fi

# 多个条件
if [[ $a -gt 0 && $a -lt 20 && $b -gt 0 ]]; then
    echo "所有条件都满足"
fi

2.2 命令连接中使用 #

bash
#!/bin/bash

# 前面命令成功才执行后面
mkdir /tmp/test && echo "目录创建成功"

# 链式执行
cd /tmp && mkdir test && cd test && echo "操作成功"

# 实际应用
ping -c 1 google.com && echo "网络正常" || echo "网络异常"

# 检查文件并执行操作
[ -f config.sh ] && source config.sh

2.3 短路求值 #

bash
#!/bin/bash

# && 的短路特性:前面为假,后面不执行
false && echo "这行不会执行"
true && echo "这行会执行"

# 利用短路特性设置默认值
name=""
[ -z "$name" ] && name="默认用户"
echo "用户名: $name"

# 条件赋值
[ -f config.env ] && source config.env

三、逻辑或 (||) #

3.1 条件判断中使用 #

bash
#!/bin/bash

a=10
b=-5

# 在 [[ ]] 中使用
if [[ $a -gt 0 || $b -gt 0 ]]; then
    echo "a或b至少有一个大于0"
fi

# 在 (( )) 中使用
if (( a > 0 || b > 0 )); then
    echo "a或b至少有一个大于0"
fi

# 多个条件
if [[ $a -gt 0 || $a -lt -10 || $b -gt 0 ]]; then
    echo "至少有一个条件满足"
fi

3.2 命令连接中使用 #

bash
#!/bin/bash

# 前面命令失败才执行后面
mkdir /tmp/test || echo "目录可能已存在"

# 默认值设置
config_file="${1:-default.conf}"

# 错误处理
cd /nonexistent || { echo "目录不存在"; exit 1; }

# 备用方案
command -v vim >/dev/null || alias vim=vi

# 检查依赖
command -v git >/dev/null || { echo "需要安装git"; exit 1; }

3.3 短路求值 #

bash
#!/bin/bash

# || 的短路特性:前面为真,后面不执行
true || echo "这行不会执行"
false || echo "这行会执行"

# 利用短路特性提供默认值
file="${1:-}"
[ -n "$file" ] || file="default.txt"
echo "使用文件: $file"

# 错误处理
cp important.txt backup.txt || { echo "备份失败"; exit 1; }

四、逻辑非 (!) #

4.1 条件取反 #

bash
#!/bin/bash

a=0

# 取反
if [[ ! $a -eq 0 ]]; then
    echo "a不等于0"
fi

# 检查文件不存在
if [[ ! -f "/tmp/test" ]]; then
    echo "文件不存在"
fi

# 检查目录不存在
if [[ ! -d "/tmp/testdir" ]]; then
    mkdir -p /tmp/testdir
fi

# 检查变量为空
if [[ ! -n "$var" ]]; then
    echo "变量为空"
fi

4.2 命令取反 #

bash
#!/bin/bash

# 命令取反
if ! ping -c 1 google.com &>/dev/null; then
    echo "网络不可用"
fi

# 检查命令不存在
if ! command -v git &>/dev/null; then
    echo "git未安装"
fi

# 检查进程不存在
if ! pgrep nginx &>/dev/null; then
    echo "nginx未运行"
fi

五、组合使用 #

5.1 && 和 || 组合 #

bash
#!/bin/bash

# 类似三元运算符
age=20
(( age >= 18 )) && echo "成年" || echo "未成年"

# 条件赋值
result=""
[[ -f config.sh ]] && result="存在" || result="不存在"
echo "配置文件$result"

# 注意:这种写法有陷阱
# 如果中间命令失败,会执行后面的命令
true && false || echo "这会执行"

# 更安全的写法
if [[ -f config.sh ]]; then
    result="存在"
else
    result="不存在"
fi

5.2 复杂逻辑组合 #

bash
#!/bin/bash

# 使用括号分组
age=25
has_license=true

if [[ ($age -ge 18 && $age -le 65) && $has_license == true ]]; then
    echo "可以驾驶"
fi

# 多条件组合
score=75
attendance=90

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

# 使用 ! 取反
if [[ ! ($score -lt 60 || $attendance -lt 80) ]]; then
    echo "通过考核"
fi

5.3 命令组合 #

bash
#!/bin/bash

# 确保目录存在
mkdir -p /tmp/myapp || { echo "创建目录失败"; exit 1; }

# 多步骤操作
cd /tmp/myapp && {
    touch config.ini
    echo "初始化完成"
} || {
    echo "操作失败"
    exit 1
}

# 检查多个条件
command -v git >/dev/null && command -v make >/dev/null || {
    echo "缺少必要工具"
    exit 1
}

六、[ ] 中的逻辑运算 #

6.1 使用 -a 和 -o #

bash
#!/bin/bash

a=10
b=5

# -a 等同于 &&
if [ $a -gt 0 -a $b -gt 0 ]; then
    echo "a和b都大于0"
fi

# -o 等同于 ||
if [ $a -gt 20 -o $b -gt 0 ]; then
    echo "a大于20或b大于0"
fi

# 使用 !
if [ ! $a -eq 0 ]; then
    echo "a不等于0"
fi

6.2 推荐使用 [[ ]] #

bash
#!/bin/bash

# 不推荐:使用 -a -o
if [ $a -gt 0 -a $b -gt 0 ]; then
    echo "不推荐写法"
fi

# 推荐:使用 [[ ]] 和 && ||
if [[ $a -gt 0 && $b -gt 0 ]]; then
    echo "推荐写法"
fi

# 或者使用单独的条件
if [ $a -gt 0 ] && [ $b -gt 0 ]; then
    echo "另一种推荐写法"
fi

七、实战示例 #

7.1 参数验证 #

bash
#!/bin/bash

validate_args() {
    # 检查参数数量
    [[ $# -lt 2 ]] && { echo "用法: $0 <文件> <模式>"; exit 1; }
    
    local file=$1
    local pattern=$2
    
    # 检查文件存在
    [[ ! -f "$file" ]] && { echo "错误: 文件 $file 不存在"; exit 1; }
    
    # 检查文件可读
    [[ ! -r "$file" ]] && { echo "错误: 文件 $file 不可读"; exit 1; }
    
    # 检查模式非空
    [[ -z "$pattern" ]] && { echo "错误: 模式不能为空"; exit 1; }
    
    echo "参数验证通过"
}

validate_args "$@"

7.2 服务检查脚本 #

bash
#!/bin/bash

check_service() {
    local service=$1
    
    # 检查服务是否存在
    if ! systemctl list-unit-files "$service.service" &>/dev/null; then
        echo "服务 $service 不存在"
        return 1
    fi
    
    # 检查服务状态
    if systemctl is-active --quiet "$service"; then
        echo "服务 $service 正在运行"
        return 0
    else
        echo "服务 $service 未运行"
        return 1
    fi
}

# 检查多个服务
services=("nginx" "mysql" "redis")
for svc in "${services[@]}"; do
    check_service "$svc" || echo "请检查 $svc 服务"
done

7.3 条件安装脚本 #

bash
#!/bin/bash

install_package() {
    local package=$1
    
    # 检查是否已安装
    if command -v "$package" &>/dev/null; then
        echo "$package 已安装"
        return 0
    fi
    
    # 检测包管理器并安装
    if command -v apt-get &>/dev/null; then
        sudo apt-get update && sudo apt-get install -y "$package"
    elif command -v yum &>/dev/null; then
        sudo yum install -y "$package"
    elif command -v brew &>/dev/null; then
        brew install "$package"
    else
        echo "未找到支持的包管理器"
        return 1
    fi
}

install_package "git"
install_package "vim"

7.4 数据验证脚本 #

bash
#!/bin/bash

validate_user_input() {
    local username=$1
    local email=$2
    local age=$3
    
    # 验证用户名
    if [[ -z "$username" ]]; then
        echo "错误:用户名不能为空"
        return 1
    fi
    
    if (( ${#username} < 3 || ${#username} > 20 )); then
        echo "错误:用户名长度应在3-20之间"
        return 1
    fi
    
    # 验证邮箱
    if [[ ! "$email" =~ ^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$ ]]; then
        echo "错误:邮箱格式不正确"
        return 1
    fi
    
    # 验证年龄
    if ! [[ "$age" =~ ^[0-9]+$ ]]; then
        echo "错误:年龄必须是数字"
        return 1
    fi
    
    if (( age < 1 || age > 150 )); then
        echo "错误:年龄应在1-150之间"
        return 1
    fi
    
    echo "验证通过"
    return 0
}

validate_user_input "张三" "test@example.com" 25

八、逻辑运算符速查 #

8.1 条件判断中 #

运算符 说明 示例
&& 逻辑与 [[ $a && $b ]]
|| 逻辑或 [[ $a || $b ]]
! 逻辑非 [[ ! $a ]]

8.2 命令连接中 #

运算符 说明 示例
&& 前面成功执行后面 cmd1 && cmd2
|| 前面失败执行后面 cmd1 || cmd2
; 顺序执行 cmd1 ; cmd2

8.3 [ ] 中的运算符 #

运算符 说明 示例
-a 逻辑与 [ $a -gt 0 -a $b -gt 0 ]
-o 逻辑或 [ $a -gt 0 -o $b -gt 0 ]
! 逻辑非 [ ! $a -eq 0 ]

九、总结 #

9.1 关键要点 #

  • && 表示逻辑与,两边都为真才为真
  • || 表示逻辑或,一边为真就为真
  • ! 表示逻辑非,取反
  • 推荐使用 [[ ]]&& ||
  • 注意短路求值的特性

9.2 下一步 #

你已经掌握了逻辑运算符,接下来让我们学习 字符串运算符,了解Shell中的字符串操作!

最后更新:2026-03-27