管道与对象
管道是 PowerShell 最核心的特性之一。与传统 shell 传递文本不同,PowerShell 管道传递的是 .NET 对象,这使得数据处理更加灵活和强大。
理解对象管道
对象 vs 文本
在传统 shell(如 bash 或 cmd)中,命令输出是文本,需要解析文本才能提取信息:
ps aux | grep chrome | awk '{print $2}'
PowerShell 传递的是对象,可以直接访问属性和方法:
Get-Process chrome | Select-Object Id
查看对象类型和成员
使用 Get-Member 查看对象的类型和可用成员:
Get-Process | Get-Member
输出示例:
TypeName: System.Diagnostics.Process
Name MemberType Definition
---- ---------- ----------
Handles AliasProperty Handles = Handlecount
Name AliasProperty Name = ProcessName
...
查看特定成员:
Get-Process | Get-Member -MemberType Property
Get-Process | Get-Member -MemberType Method
管道操作符
基本管道
使用 | 将一个命令的输出传递给另一个命令:
Get-Service | Where-Object { $_.Status -eq "Running" }
链式管道
多个命令可以串联:
Get-Process |
Where-Object { $_.CPU -gt 100 } |
Sort-Object CPU -Descending |
Select-Object -First 5
筛选对象
Where-Object
Where-Object 根据条件过滤对象:
Get-Service | Where-Object { $_.Status -eq "Running" }
简化语法(PowerShell 3.0+):
Get-Service | Where-Object Status -eq "Running"
使用多个条件:
Get-Process | Where-Object { $_.CPU -gt 100 -and $_.WorkingSet -gt 100MB }
使用 -or 逻辑:
Get-Service | Where-Object { $_.Status -eq "Running" -or $_.Status -eq "Stopped" }
Select-Object
Select-Object 选择对象的特定属性:
Get-Process | Select-Object Name, Id, CPU
选择前 N 个对象:
Get-Process | Select-Object -First 5
Get-Process | Select-Object -Last 5
跳过对象:
Get-Process | Select-Object -Skip 5
Get-Process | Select-Object -Skip 5 -First 5
选择唯一值:
Get-Process | Select-Object Name -Unique
创建计算属性:
Get-Process | Select-Object Name,
@{Name="Memory(MB)";Expression={[math]::Round($_.WorkingSet / 1MB, 2)}}
Select-String
在文本中搜索模式:
Get-Content "C:\Logs\app.log" | Select-String "Error"
使用正则表达式:
Get-Content "C:\Logs\app.log" | Select-String "\d{4}-\d{2}-\d{2}"
搜索文件内容:
Select-String -Path "C:\Logs\*.log" -Pattern "Exception" -Context 2,2
排序对象
Sort-Object
按属性排序:
Get-Process | Sort-Object CPU
Get-Process | Sort-Object CPU -Descending
按多个属性排序:
Get-Process | Sort-Object CPU -Descending, Name
使用计算属性排序:
Get-ChildItem | Sort-Object { $_.Length } -Descending
分组对象
Group-Object
按属性分组:
Get-Service | Group-Object Status
输出示例:
Count Name Group
----- ---- -----
87 Running {AdobeARMservice, Appinfo, AudioSrv...}
12 Stopped {AJRouter, ALG, AppMgmt...}
按计算属性分组:
Get-ChildItem | Group-Object Extension
使用 -NoElement 省略组成员:
Get-Service | Group-Object Status -NoElement
统计对象
Measure-Object
计算统计值:
Get-Process | Measure-Object WorkingSet -Sum -Average -Maximum -Minimum
统计行数:
Get-Content "file.txt" | Measure-Object -Line
统计字符数:
"Hello World" | Measure-Object -Character -Word
比较对象
Compare-Object
比较两个对象集合:
$set1 = 1, 2, 3, 4, 5
$set2 = 3, 4, 5, 6, 7
Compare-Object $set1 $set2
输出:
InputObject SideIndicator
----------- -------------
6 =>
7 =>
1 <=
2 <=
<=表示只在第一个集合中存在=>表示只在第二个集合中存在
比较文件内容:
Compare-Object (Get-Content "file1.txt") (Get-Content "file2.txt")
比较对象属性:
Compare-Object $list1 $list2 -Property Name, Id
格式化输出
Format-Table
表格格式输出:
Get-Process | Format-Table Name, Id, CPU -AutoSize
自动换行:
Get-Process | Format-Table Name, Id, CPU -Wrap
Format-List
列表格式输出:
Get-Process chrome | Format-List *
指定属性:
Get-Process | Format-List Name, Id, CPU, WorkingSet
Format-Wide
宽格式输出,每行显示多个对象:
Get-Service | Format-Wide Name -Column 4
Format-Custom
自定义视图:
Get-Process | Format-Custom
导出数据
Export-Csv
导出为 CSV 文件:
Get-Process | Export-Csv -Path "processes.csv" -NoTypeInformation
追加到现有文件:
Get-Process | Export-Csv -Path "processes.csv" -Append
ConvertTo-Csv
转换为 CSV 字符串:
Get-Process | Select-Object Name, Id, CPU | ConvertTo-Csv
Export-Clixml
导出为 XML 格式,保留类型信息:
Get-Process | Export-Clixml -Path "processes.xml"
导入:
Import-Clixml -Path "processes.xml"
ConvertTo-Json
转换为 JSON 格式:
Get-Process chrome | Select-Object Name, Id, CPU | ConvertTo-Json
指定深度:
$object | ConvertTo-Json -Depth 5
ConvertTo-Html
转换为 HTML 格式:
Get-Process | ConvertTo-Html -Property Name, Id, CPU |
Out-File "processes.html"
添加标题和 CSS:
Get-Process |
ConvertTo-Html -Title "进程列表" -CssUri "style.css" |
Out-File "processes.html"
Tee-Object
同时输出到文件和管道:
Get-Process | Tee-Object -FilePath "processes.txt" | Select-Object -First 5
输出到变量:
Get-Process | Tee-Object -Variable processes | Select-Object -First 5
$processes | Measure-Object
管道实战示例
分析日志文件
Get-Content "C:\Logs\app.log" |
Where-Object { $_ -match "ERROR" } |
ForEach-Object {
if ($_ -match "(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}) ERROR (.+)") {
[PSCustomObject]@{
Timestamp = $matches[1]
Message = $matches[2]
}
}
} |
Group-Object { $_.Timestamp.Split(' ')[0] } |
Sort-Object Count -Descending |
Select-Object Name, Count |
Format-Table -AutoSize
查找大文件
Get-ChildItem -Path "C:\" -Recurse -ErrorAction SilentlyContinue |
Where-Object { -not $_.PSIsContainer -and $_.Length -gt 100MB } |
Select-Object FullName,
@{Name="Size(MB)";Expression={[math]::Round($_.Length/1MB, 2)}},
LastWriteTime |
Sort-Object "Size(MB)" -Descending |
Format-Table -AutoSize
服务状态报告
Get-Service |
Group-Object Status |
Select-Object Name, Count |
Format-Table -AutoSize
Get-Service |
Where-Object { $_.Status -eq "Stopped" -and $_.StartType -eq "Automatic" } |
Select-Object Name, DisplayName, Status |
Format-Table -AutoSize
进程资源分析
Get-Process |
Where-Object { $_.WorkingSet -gt 100MB } |
Select-Object Name,
@{Name="CPU(s)";Expression={[math]::Round($_.CPU, 2)}},
@{Name="Memory(MB)";Expression={[math]::Round($_.WorkingSet/1MB, 2)}},
@{Name="Handles";Expression={$_.HandleCount}} |
Sort-Object "Memory(MB)" -Descending |
Format-Table -AutoSize
系统信息收集
$systemInfo = [PSCustomObject]@{
ComputerName = $env:COMPUTERNAME
OS = (Get-CimInstance Win32_OperatingSystem).Caption
CPU = (Get-CimInstance Win32_Processor).Name
TotalMemory = [math]::Round((Get-CimInstance Win32_ComputerSystem).TotalPhysicalMemory/1GB, 2)
FreeMemory = [math]::Round((Get-CimInstance Win32_OperatingSystem).FreePhysicalMemory/1MB, 2)
DiskSpace = Get-Volume -DriveLetter C | Select-Object -ExpandProperty SizeRemaining
}
$systemInfo | Format-List
下一步
掌握了管道与对象后,接下来学习 常用 Cmdlet,了解日常管理中最常用的命令。