PowerShell 的控制结构(流程控制)非常丰富、统一、强大,而且几乎全部都“对象友好”,写起来比传统批处理/Bash 爽太多。
下面按实际使用频率和重要性,从高到低系统梳理一遍,配上最实用的写法和防坑技巧。
1. if / elseif / else(最常用)
$age = 18
if ($age -lt 13) {
"儿童"
}
elseif ($age -lt 18) {
"青少年"
}
elseif ($age -lt 60) {
"成年人"
}
else {
"老年人"
}
# 推荐写法:一行写法(很常见)
if (Test-Path $path) { Remove-Item $path -Force }
常见比较运算符(区分大小写!)
| 类型 | 相等 | 不等 | 大于 | 小于 | 包含 | 匹配正则 | 类型判断 |
|---|---|---|---|---|---|---|---|
| 区分大小写 | -eq | -ne | -gt | -lt | -contains | -match | -is |
| 不区分大小写 | -ieq | -ine | -igt | -ilt | -icontains | -imatch | -isnot |
| 正则专用 | -ceq | -cne | -cgt | -clt | -in | -inotmatch | -like / -notlike |
| -notin | -cmatch | -ilike |
示例:
if ($env:USERNAME -ceq "ADMIN") { "大小写精确匹配" }
if ($list -contains $item) { "集合包含判断" }
if ($path -like "*\Windows\*") { "通配符匹配" }
if ($text -match "^\d{11}$") { "正则匹配手机号" }
2. switch(PowerShell 最强大、最好用的控制结构)
基本语法(支持字符串、数字、数组、文件、甚至对象集合!)
switch ($os)
{
"Windows" { "是 Windows" }
"Linux" { "是 Linux" }
"Darwin" { "是 macOS" }
default { "未知系统" }
}
超实用高级特性(其他语言基本没有)
# 1. 支持正则匹配(加 -regex)
switch -Regex ($line)
{
'^\d{4}-\d{2}-\d{2}' { "这是日期行" }
'ERROR|FAIL' { "错误日志" }
'WARNING' { "警告日志" }
}
# 2. 支持通配符(-Wildcard)
switch -Wildcard ($file.Extension)
{
*.exe { "可执行文件" }
*.dll { "动态库" }
*.ps1 { "PowerShell 脚本" }
}
# 3. 支持文件读取(最牛!一行处理整个文件)
switch -File "C:\logs\app.log"
{
{$_ -match "ERROR"} { Write-Host "发现错误: $_" -ForegroundColor Red }
{$_ -match "WARN"} { Write-Host "警告: $_" -ForegroundColor Yellow }
default { Write-Debug "普通日志: $_" }
}
# 4. 支持集合自动展开(对数组直接遍历)
$processes = Get-Process
switch ($processes)
{
{$_.CPU -gt 1000} { "$($_.Name) CPU 占用过高" }
{$_.Handles -gt 1000} { "$($_.Name) 句柄泄漏嫌疑" }
}
switch 最佳参数组合(背下来就无敌)
switch -Regex -File $logPath { ... } # 处理大日志最快
switch -CaseSensitive ($choice) { ... } # 区分大小写
switch -Wildcard -File $list { ... }
3. for 循环(用得少,但某些场景必须)
# 经典计数循环
for ($i = 1; $i -le 10; $i++) {
Write-Progress -Activity "处理中" -PercentComplete ($i*10)
Start-Sleep -Milliseconds 300
}
# 修改数组时必须用传统 for(foreach 会报错)
$array = 1..5
for ($i=0; $i -lt $array.Count; $i++) {
$array[$i] *= 10
}
4. foreach(PowerShell 里最常用循环)
# 方式1:最快(推荐)
foreach ($file in $files) {
$file.Name
}
# 方式2:管道方式(最常见,但比上面慢 5-50 倍)
$files | ForEach-Object { $_.Name }
# 方式3:别名(最常用写法)
Get-ChildItem | % { $_.FullName }
# 方式4:PS7+ 超快新语法(推荐大集合)
$files.ForEach{ $_.Length }
性能排序(10万条数据)
$list = 1..100000
# 最快:foreach 语句
foreach ($i in $list) { $null }
# 次快:.ForEach() 方法(PS7+)
$list.ForEach{ $null }
# 中等:ForEach-Object
$list | ForEach-Object { $null }
# 最慢:ForEach-Object 别名 %
$list | % { $null }
5. while / do-while / do-until
# while(先判断后执行)
while ($i -lt 10) {
$i++
}
# do-while(至少执行一次)
do {
$input = Read-Host "输入 q 退出"
} while ($input -ne 'q')
# do-until(直到条件为真才停)
$num = 0
do {
$
num = Get-Random -Maximum 100
“随机数: $num”
} until ($num -eq 77)
### 6. break / continue / return / exit 的区别(常被混淆)
| 关键字 | 作用范围 | 常用场景 |
|-----------|------------------------------|------------------------------------------|
| break | 跳出当前循环(for/switch/while)| switch 中跳到 default 后 break |
| continue | 跳过本次循环,进入下一次 | foreach 里跳过某些文件 |
| return | 立即返回函数/脚本的结果 | 函数提前返回 |
| exit | 立即退出整个 PowerShell 进程 | 脚本验证失败直接终止 |
| throw | 抛出终止性错误 | 参数校验失败 |
示例:
powershell
1..100 | ForEach-Object {
if ($_ % 15 -eq 0) { return “找到 15 的倍数: $_” } # 只返回第一个
if ($_ % 3 -eq 0) { continue } # 跳过 3 的倍数
}
### 7. try / catch / finally(异常处理)
powershell
try {
Get-Item “C:\不存在的文件.txt” -ErrorAction Stop
}
catch [System.IO.FileNotFoundException] {
“文件真的没找到!”
}
catch {
“其他错误: $($_.Exception.Message)”
}
finally {
“无论如何都会执行的清理代码”
}
“`
必知技巧:
- 只有加了
-ErrorAction Stop或$ErrorActionPreference = 'Stop'才会进入 catch $_.Exception、$_.TargetObject、$_.InvocationInfo是调试神器
8. 终极总结:PowerShell 控制结构优先级口诀
- 能用 switch 绝不用 if(特别是处理字符串、日志、正则时)
- 能用 foreach 语句 绝不用 ForEach-Object(性能差太多)
- 99% 的循环用 foreach 或 .ForEach() 就够了
- 能用管道就用管道,管道才是 PowerShell 的灵魂
- 参数校验失败直接 throw,配合 try/catch 最优雅
- 永远记得 -ErrorAction Stop 才能 catch
把上面这些吃透,你写的 PowerShell 脚本就从“能跑”进化到“专业级、又快又优雅”。
有任何控制结构相关的代码想优化或重构,随时贴出来,我帮你改成最 PowerShell 味的写法!