Day-4-运算符与表达式

Day 4: 运算符与表达式

🎯 学习目标

  • 理解 PowerShell 中各种运算符的作用和用法
  • 掌握算术运算符进行数学计算
  • 学会比较运算符进行条件判断
  • 使用逻辑运算符组合多个条件
  • 了解字符串运算符的特殊用法
  • 掌握运算符的优先级规则

💡 核心概念

什么是运算符?

运算符是用于执行操作的符号或关键字。在 PowerShell 中,运算符可以用于:

  • 数学计算
  • 字符串操作
  • 比较值的大小
  • 逻辑判断
  • 类型转换

什么是表达式?

表达式是由运算符、操作数(变量、值、函数调用等)组合而成的式子,可以被 PowerShell 求值并产生结果。

示例:

# 简单表达式
5 + 3

# 复杂表达式
($age -ge 18) -and ($hasLicense -eq $true)

📝 算术运算符

算术运算符用于执行数学运算。

基本算术运算符

运算符 名称 示例 结果
+ 加法 5 + 3 8
- 减法 10 - 4 6
* 乘法 6 * 7 42
/ 除法 15 / 3 5
% 取模(余数) 10 % 3 1

示例代码

# 基本算术运算
$a = 10
$b = 3

$sum = $a + $b          # 13
$difference = $a - $b   # 7
$product = $a * $b      # 30
$quotient = $a / $b     # 3.3333...
$remainder = $a % $b    # 1

Write-Host "加法: $sum"
Write-Host "减法: $difference"
Write-Host "乘法: $product"
Write-Host "除法: $quotient"
Write-Host "余数: $remainder"

实际应用:计算购物总价

# 场景:计算购物总价
$price = 59.9
$quantity = 3
$taxRate = 0.08

# 计算小计
$subtotal = $price * $quantity

# 计算税额
$tax = $subtotal * $taxRate

# 计算总价
$total = $subtotal + $tax

Write-Host "商品单价: ¥$price"
Write-Host "购买数量: $quantity"
Write-Host "小计: ¥$subtotal"
Write-Host "税额: ¥$tax"
Write-Host "总价: ¥$total"

📝 赋值运算符

赋值运算符用于给变量赋值。

常用赋值运算符

运算符 名称 示例 等价于
= 简单赋值 $a = 5
+= 加并赋值 $a += 3 $a = $a + 3
-= 减并赋值 $a -= 2 $a = $a - 2
*= 乘并赋值 $a *= 4 $a = $a * 4
/= 除并赋值 $a /= 2 $a = $a / 2
%= 取模并赋值 $a %= 3 $a = $a % 3

示例代码

# 基本赋值
$count = 0
Write-Host "初始值: $count"  # 0

# 加并赋值
$count += 5
Write-Host "加5后: $count"   # 5

# 减并赋值
$count -= 2
Write-Host "减2后: $count"   # 3

# 乘并赋值
$count *= 4
Write-Host "乘4后: $count"   # 12

# 除并赋值
$count /= 3
Write-Host "除以3后: $count" # 4

实际应用:计数器

# 场景:统计文件数量
$fileCount = 0

# 模拟处理多个文件
$files = @("doc1.txt", "doc2.txt", "doc3.txt", "doc4.txt")

foreach ($file in $files) {
    Write-Host "处理文件: $file"
    $fileCount += 1  # 每处理一个文件,计数器加1
}

Write-Host "`n总共处理了 $fileCount 个文件"

📝 比较运算符

比较运算符用于比较两个值,返回 TrueFalse

PowerShell 特殊语法

⚠️ 重要:PowerShell 的比较运算符不是传统的符号(如 ==, >, <),而是字母组合!

运算符 名称 示例 说明
-eq 等于 5 -eq 5 等于返回 True
-ne 不等于 5 -ne 3 不等于返回 True
-gt 大于 10 -gt 5 大于返回 True
-ge 大于等于 10 -ge 10 大于等于返回 True
-lt 小于 3 -lt 5 小于返回 True
-le 小于等于 3 -le 3 小于等于返回 True

大小写不敏感版本

运算符 说明
-ieq, -ine, -igt, -ige, -ilt, -ile` 显式大小写不敏感(默认)
-ceq, -cne, -cgt, -cge, -clt, -cle 大小写敏感

示例代码

# 数值比较
$age = 25

$isAdult = $age -ge 18
Write-Host "是否成年: $isAdult"  # True

$isSenior = $age -ge 60
Write-Host "是否老年: $isSenior" # False

# 字符串比较(默认大小写不敏感)
$name1 = "PowerShell"
$name2 = "powershell"

$isSame = $name1 -eq $name2
Write-Host "名称相同: $isSame"  # True(因为不区分大小写)

# 字符串比较(大小写敏感)
$isSameCase = $name1 -ceq $name2
Write-Host "名称完全相同: $isSameCase"  # False(区分大小写)

实际应用:成绩判断

# 场景:判断成绩等级
$score = 85

if ($score -ge 90) {
    Write-Host "优秀"
} elseif ($score -ge 80) {
    Write-Host "良好"
} elseif ($score -ge 60) {
    Write-Host "及格"
} else {
    Write-Host "不及格"
}
# 输出: 良好

📝 逻辑运算符

逻辑运算符用于组合多个条件,返回 TrueFalse

基本逻辑运算符

运算符 名称 说明 示例
-and 两个条件都为 True 时返回 True $age -ge 18 -and $hasLicense
-or 两个条件任一为 True 时返回 True $isStudent -or $isSenior
-xor 异或 两个条件有且仅有一个为 True 时返回 True $a -xor $b
-not 取反 -not ($isReady)
! -not 的简写 ! $isReady

逻辑运算符真值表

A B A -and B A -or B A -xor B
True True True True False
True False False True True
False True False True True
False False False False False

示例代码

# -and 运算符:两个条件都必须为真
$age = 25
$hasLicense = $true

$canDrive = ($age -ge 18) -and $hasLicense
Write-Host "可以开车: $canDrive"  # True

# -or 运算符:至少一个条件为真
$isStudent = $false
$isSenior = $true

$hasDiscount = $isStudent -or $isSenior
Write-Host "有折扣: $hasDiscount"  # True

# -not 运算符:取反
$isReady = $false
$isNotReady = -not $isReady
Write-Host "未准备好: $isNotReady"  # True

实际应用:登录验证

# 场景:用户登录验证
$username = "admin"
$password = "secret123"
$isActive = $true
$isLocked = $false

# 验证条件:用户名正确 且 密码正确 且 账户激活 且 未锁定
$isValid = ($username -eq "admin") -and `
           ($password -eq "secret123") -and `
           $isActive -and `
           (-not $isLocked)

if ($isValid) {
    Write-Host "登录成功!"
} else {
    Write-Host "登录失败,请检查用户名和密码。"
}

实际应用:文件筛选

# 场景:查找大文件且最近修改过的文件
$files = Get-ChildItem "C:\Logs"

foreach ($file in $files) {
    # 筛选条件:大于1MB 且 在7天内修改过
    if (($file.Length -gt 1MB) -and ($file.LastWriteTime -gt (Get-Date).AddDays(-7))) {
        Write-Host "发现大文件: $($file.Name) - 大小: $([math]::Round($file.Length / 1MB, 2)) MB"
    }
}

📝 字符串运算符

字符串运算符用于字符串的比较和操作。

字符串比较运算符

运算符 名称 说明
-eq, -ne, -gt, -ge, -lt, -le 比较 按字母顺序比较
-like, -notlike 通配符匹配 支持通配符 *, ?, []
-match, -notmatch 正则表达式匹配 使用正则表达式

字符串连接运算符

运算符 名称 示例 结果
+ 连接 "Hello" + " " + "World" "Hello World"
* 重复 "A" * 5 "AAAAA"

示例代码

# 字符串连接
$firstName = "张"
$lastName = "三"
$fullName = $firstName + $lastName
Write-Host "姓名: $fullName"  # 张三

# 字符串重复
$separator = "-" * 20
Write-Host $separator  # --------------------

# 通配符匹配
$filename = "report2024.xlsx"
$isExcelFile = $filename -like "*.xlsx"
Write-Host "是Excel文件: $isExcelFile"  # True

# 正则表达式匹配
$email = "user@example.com"
$isValidEmail = $email -match "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$"
Write-Host "有效邮箱: $isValidEmail"  # True

实际应用:文件筛选

# 场景:筛选特定类型的文件
$files = @("report.docx", "data.xlsx", "image.jpg", "backup.zip", "summary.docx")

foreach ($file in $files) {
    # 筛选 Word 文档
    if ($file -like "*.docx") {
        Write-Host "Word文档: $file"
    }
}

# 输出:
# Word文档: report.docx
# Word文档: summary.docx

实际应用:数据验证

# 场景:验证输入数据格式
$phone = "13812345678"

# 验证手机号格式(11位数字)
$isValidPhone = $phone -match "^\d{11}$"
if ($isValidPhone) {
    Write-Host "手机号格式正确"
} else {
    Write-Host "手机号格式错误"
}

📝 运算符优先级

当一个表达式中包含多个运算符时,PowerShell 按照优先级顺序执行。

优先级从高到低

优先级 运算符类型 运算符
1(最高) 括号 ()
2 一元运算符 -, +, --, ++, !, -not
3 乘除模 *, /, %
4 加减 +, -
5 比较运算符 -eq, -ne, -gt, -ge, -lt, -le
6 逻辑与 -and
7(最低) 逻辑或 -or

示例代码

# 优先级示例
$result1 = 2 + 3 * 4    # 结果: 14(先乘后加)
$result2 = (2 + 3) * 4  # 结果: 20(括号优先)

Write-Host "2 + 3 * 4 = $result1"      # 14
Write-Host "(2 + 3) * 4 = $result2"    # 20

# 逻辑运算符优先级
$age = 25
$isStudent = $true

# -and 优先级高于 -or
$result3 = $age -lt 18 -or $isStudent -and $age -lt 25
# 相当于: $age -lt 18 -or ($isStudent -and $age -lt 25)
# False -or (True -and False) = False

Write-Host "结果: $result3"  # False

# 使用括号明确优先级
$result4 = ($age -lt 18 -or $isStudent) -and $age -lt 25
# (False -or True) -and False = False

Write-Host "结果: $result4"  # False

建议

⚠️ 重要:当表达式复杂时,始终使用括号明确优先级,即使默认顺序正确也要加括号。这样做的好处是:

  • 代码更易读
  • 避免歧义
  • 防止未来维护时出错
# 推荐:使用括号
$isValid = ($age -ge 18) -and ($hasLicense -eq $true)

# 不推荐:依赖默认优先级
$isValid = $age -ge 18 -and $hasLicense -eq $true

🎮 完整实战示例

示例1:计算器脚本

# 场景:简单计算器

Write-Host "=== PowerShell 计算器 ===" -ForegroundColor Cyan
Write-Host ""

# 获取用户输入
$num1 = Read-Host "请输入第一个数字"
$operator = Read-Host "请输入运算符 (+, -, *, /, %)"
$num2 = Read-Host "请输入第二个数字"

# 转换为数字
$number1 = [double]$num1
$number2 = [double]$num2

# 计算结果
$result = 0
$isValid = $true

switch ($operator) {
    "+" { $result = $number1 + $number2 }
    "-" { $result = $number1 - $number2 }
    "*" { $result = $number1 * $number2 }
    "/" {
        if ($number2 -eq 0) {
            Write-Host "错误:除数不能为零!" -ForegroundColor Red
            $isValid = $false
        } else {
            $result = $number1 / $number2
        }
    }
    "%" { $result = $number1 % $number2 }
    default {
        Write-Host "错误:不支持的运算符!" -ForegroundColor Red
        $isValid = $false
    }
}

# 显示结果
if ($isValid) {
    Write-Host ""
    Write-Host "计算结果: $number1 $operator $number2 = $result" -ForegroundColor Green
}

示例2:温度转换器

# 场景:温度单位转换(摄氏度 ↔ 华氏度)

Write-Host "=== 温度转换器 ===" -ForegroundColor Cyan
Write-Host ""

# 获取用户输入
$temp = Read-Host "请输入温度值"
$unit = Read-Host "请选择单位 (C=摄氏度, F=华氏度)"

# 转换为数字
$temperature = [double]$temp

# 转换温度
if ($unit -eq "C" -or $unit -eq "c") {
    # 摄氏度转华氏度
    $fahrenheit = $temperature * 9 / 5 + 32
    Write-Host "$temperature°C = $fahrenheit°F"
} elseif ($unit -eq "F" -or $unit -eq "f") {
    # 华氏度转摄氏度
    $celsius = ($temperature - 32) * 5 / 9
    Write-Host "$temperature°F = $celsius°C"
} else {
    Write-Host "无效的单位!" -ForegroundColor Red
}

示例3:成绩统计系统

# 场景:学生成绩统计

Write-Host "=== 成绩统计系统 ===" -ForegroundColor Cyan
Write-Host ""

# 获取学生成绩
$chinese = [int](Read-Host "语文成绩")
$math = [int](Read-Host "数学成绩")
$english = [int](Read-Host "英语成绩")

# 计算总分和平均分
$totalScore = $chinese + $math + $english
$averageScore = $totalScore / 3

# 四舍五入到两位小数
$averageScore = [math]::Round($averageScore, 2)

Write-Host ""
Write-Host "=== 成绩单 ===" -ForegroundColor Green
Write-Host "语文: $chinese"
Write-Host "数学: $math"
Write-Host "英语: $english"
Write-Host "总分: $totalScore"
Write-Host "平均分: $averageScore"
Write-Host ""

# 判断等级
if ($averageScore -ge 90) {
    Write-Host "等级: 优秀" -ForegroundColor Green
} elseif ($averageScore -ge 80) {
    Write-Host "等级: 良好" -ForegroundColor Cyan
} elseif ($averageScore -ge 60) {
    Write-Host "等级: 及格" -ForegroundColor Yellow
} else {
    Write-Host "等级: 不及格" -ForegroundColor Red
}

# 判断是否所有科目都及格
$allPass = ($chinese -ge 60) -and ($math -ge 60) -and ($english -ge 60)
if ($allPass) {
    Write-Host "恭喜!所有科目都及格了!" -ForegroundColor Green
} else {
    Write-Host "注意:有科目不及格,需要努力!" -ForegroundColor Red
}

⚠️ 重要注意事项

1. 比较运算符的特殊语法

⚠️ 常见错误:初学者常写成传统符号

# ❌ 错误写法
if ($age == 18) { }    # 错误!
if ($age > 18) { }     # 错误!

# ✅ 正确写法
if ($age -eq 18) { }   # 正确
if ($age -gt 18) { }   # 正确

2. 字符串比较默认不区分大小写

# 默认不区分大小写
"HELLO" -eq "hello"  # 返回 True

# 如需区分大小写,使用 -c 前缀
"HELLO" -ceq "hello"  # 返回 False

3. 除法运算的结果类型

# 整数除法可能返回小数
$result = 10 / 3  # 结果是 3.3333...,不是整数

# 如需整数除法,使用 [int] 转换或取整函数
$result = [int](10 / 3)  # 3(截断)
$result = [Math]::Floor(10 / 3)  # 3(向下取整)
$result = [Math]::Round(10 / 3)  # 3(四舍五入)

4. 逻辑运算符的短路特性

# -and 运算符:第一个条件为 False,不会计算第二个条件
$result = $false -and (1 / 0)  # 不会报错,因为第一个条件为 False

# -or 运算符:第一个条件为 True,不会计算第二个条件
$result = $true -or (1 / 0)   # 不会报错,因为第一个条件为 True

5. 运算符两侧空格不影响结果

# 以下写法都是正确的
$result = 5+3        # 紧凑
$result = 5 + 3      # 推荐:有空格
$result = 5  +  3    # 多个空格(不推荐)

建议:运算符两侧加空格,提高代码可读性。


✍️ 练习任务

基础练习

  1. 计算练习

    • 创建脚本,计算圆的面积和周长(用户输入半径)
    • 提示:面积 = π × r²,周长 = 2 × π × r
    • π 的值:[Math]::PI
  2. 比较练习

    • 让用户输入年龄
    • 判断并输出:未成年(<18)、成年(18-60)、老年(>60)
  3. 逻辑练习

    • 判断一个年份是否为闰年
    • 闰年规则:能被4整除但不能被100整除,或者能被400整除

进阶练习

  1. 简易购物系统

    • 用户输入商品单价和数量
    • 根据数量计算折扣(≥10件9折,≥50件8折)
    • 计算并显示小计、折扣、税额(8%)、总价
  2. 文件管理助手

    • 获取指定目录下的所有文件
    • 统计文件总数、总大小
    • 筛选并显示大于指定大小的文件
  3. 成绩等级判定

    • 用户输入三门课成绩
    • 计算总分、平均分、等级
    • 判断是否有不及格科目
    • 输出详细的成绩报告

实战挑战

  1. BMI 计算器

    • 用户输入身高(米)和体重(公斤)
    • 计算 BMI:体重 / (身高 × 身高)
    • 判断健康状态:
      • BMI < 18.5:偏瘦
      • 18.5 ≤ BMI < 24:正常
      • 24 ≤ BMI < 28:超重
      • BMI ≥ 28:肥胖
  2. 密码强度检测器

    • 用户输入密码
    • 检测密码强度并返回评分:
      • 长度 ≥ 8:+10分
      • 包含大写字母:+20分
      • 包含小写字母:+10分
      • 包含数字:+20分
      • 包含特殊字符:+30分
      • 总分 ≥ 60:弱
      • 总分 ≥ 80:中
      • 总分 ≥ 90:强

💡 常见问题 FAQ

Q1: 为什么 PowerShell 的比较运算符不是 == 而是 -eq

A: 这是 PowerShell 的设计选择,原因包括:

  • 避免与赋值运算符 = 混淆
  • 统一的运算符命名规则(都以 - 开头)
  • 更清晰的语法,易于阅读

Q2: -eq-ceq 有什么区别?

A:

  • -eq:大小写不敏感(默认),"A" -eq "a" 返回 True
  • -ceq:大小写敏感,"A" -ceq "a" 返回 False
  • 类似的,-gt, -lt 等都有 -c 前缀版本

Q3: 如何判断一个变量是否为 null?

A: 使用 $null 比较:

if ($value -eq $null) {
    Write-Host "变量为空"
}

Q4: 字符串连接用 + 还是双引号更高效?

A:

  • 少量连接:性能差异不大,选择更易读的方式
  • 大量连接:建议使用 StringBuilder
  • 推荐使用双引号变量插值:"$firstName $lastName"

Q5: 为什么 1/2 的结果是 0 而不是 0.5?

A: 在 PowerShell 中,整数相除会自动转换为浮点数:

$result = 1 / 2      # 结果是 0.5
$result = 1.0 / 2    # 结果也是 0.5

如果确实需要整数除法,使用 [int] 转换或取整函数。


📚 拓展阅读

推荐资源

  1. 官方文档

  2. 学习建议

    • 多练习运算符的组合使用
    • 注意比较运算符的特殊语法
    • 熟练掌握逻辑运算符的优先级
    • 使用括号明确优先级
  3. 下一步学习

    • 条件判断语句(if, elseif, else)
    • 循环结构(for, foreach, while)
    • 函数的定义和调用

恭喜!你已经掌握了 PowerShell 的运算符与表达式! 🎉

这些基础知识是后续学习的基石,请务必多加练习,灵活运用!