PowerShell 第11章:过滤和比较(下)
PowerShell 第11章:过滤和比较(下)
Where-Object、迭代命令行模型、常见坑位与练习
目标:把比较运算符真正“嵌”进管道,用
Where-Object
写出可读、可维护、性能可控的过滤命令;掌握迭代式构建管道的方法。
1️⃣ Where-Object:万能过滤器
1.1 标准语法(推荐记忆)
Get-Service | Where-Object { $_.Status -eq 'Running' }
# 读作:Where(对象的)Status 等于 Running
$_
:管道占位符,一次只表示当前处理的那个对象。{ ... }
:FilterScript,返回$true/$false
即可。
1.2 v3 简写(了解)
Get-Service | Where Status -eq 'Running'
简写适合单条件;多条件、多行或含
$_
的表达式,请用标准语法,可读性远好于堆叠简写。
1.3 多条件示例
# 同时筛选:正在运行 && 启动类型为手动
Get-Service | Where-Object {
$_.Status -eq 'Running' -and $_.StartType -eq 'Manual'
}
2️⃣ 迭代命令行模型(PSICLM):把复杂需求拆成 5 步
思想:不要企图一次写完终极命令,先跑通最小子问题,再“向上箭头”叠加。
需求:统计“除 PowerShell 进程外,虚拟内存(VM)占用最高的 10 个进程”的 VM 总和。
拆解 & 叠加命令:
# 1. 取进程
Get-Process
# 2. 排除 PowerShell 本体
Get-Process | Where-Object { $_.Name -notlike 'powershell*' }
# 3. 按 VM 排序(降序)
... | Sort-Object VM -Descending
# 4. 只要 Top 10
... | Select-Object -First 10
# 5. 求 VM 总和(Measure-Object)
... | Measure-Object -Property VM -Sum
随时按 ↑ 找回上一条命令小步修改;每一步都要看输出,确保在正确轨道上。
3️⃣ $_
到底什么时候能用?
只能在支持 FilterScript 的场合使用(如
Where-Object
、ForEach-Object
等)。括号里的子管道也会产生自己的
$_
作用域,务必分清:Get-Service -ComputerName ( Get-Content .\names.txt | Where-Object { $_ -notlike '*dc' } # 这里的 $_ 是“字符串(计算机名)” ) | Where-Object { $_.Status -eq 'Running' } # 这里的 $_ 是“服务对象”
4️⃣ 远程/性能意识:把过滤“推到数据源”
先过滤后传输永远更省:
- AD:用
-Filter
把对象数量压到最少; - 远程:考虑用远程会话在目标机执行
Where-Object
(第13章见)。
- AD:用
避免在本地装载海量对象再过滤,尤其跨网络时。
5️⃣ 常见坑位 & 规避
把
Where-Object
当第一选择- ✅ 优先考虑左过滤:能
-Filter
就别Where
。
- ✅ 优先考虑左过滤:能
混淆“列头名”和“属性名”
- 用
Get-Member
(或Format-List *
)查真实属性名。 - 例:
Get-Process
的列头 “PM(K)” 实际属性是PM
。
- 用
在不支持的上下文使用
$_
- 只在
Where-Object {}
、ForEach-Object {}
等能识别它的地方用。
- 只在
括号子管道的作用域
- 括号里的
$_
与外层$_
不是同一个,分清对象类型。
- 括号里的
6️⃣ 经典实战清单(带答案思路)
均来自本章练习,方便你检验掌握度。
物理网卡列表(Windows 8+/2012+)
Import-Module NetAdapter Get-NetAdapter -Physical
DNS 缓存中的 A / AAAA 记录
Import-Module DnsClient Get-DnsClientCache -Type A,AAAA
System32 下 > 5MB 的 EXE
Get-ChildItem C:\Windows\System32\*.exe | Where-Object { $_.Length -gt 5MB }
仅列“安全更新”的补丁
Get-HotFix -Description 'Security Update'
名为 Conhost 或 Svchost 且“运行中”的进程
Get-Process -Name conhost, svchost | Where-Object { $_.Responding } # 或 Get-Process | Where-Object { $_.Name -in @('conhost','svchost') -and $_.Responding }
7️⃣ 快速对照卡(可打印)
- 优先:
-Filter
>Where-Object
- 位置:过滤越靠左越好、越靠近数据源越好
- 匹配:
-like
(通配符)/-match
(正则) - 大小写:默认不敏感,敏感用
-c*
- 布尔:
-and
/-or
/-not
- 属性名:不信列头名,信
Get-Member