编码 · 编程语言
PowerShell 入门教程
简短回答
PowerShell 是微软推出的跨平台 Shell 和自动化脚本语言。它的命令称为 cmdlet,通过管道传递的是 .NET 对象而不是纯文本,因此无需解析文本即可过滤、排序和导出数据。本页涵盖安装 PowerShell 7、运行脚本、cmdlet、变量、运算符、流程控制、函数、集合和错误处理。
打开正则测试PowerShell 是什么,用来做什么
PowerShell 是微软推出的基于 .NET 的跨平台 Shell 和脚本语言。传统 Shell 在命令之间传递纯文本,而 PowerShell 传递带有属性和方法的 .NET 对象,所以无需解析文本就能过滤和排序数据。
系统管理员和 DevOps 工程师用 PowerShell 自动化 Windows 管理、管理 Active Directory、Microsoft 365 和 Azure,以及编写构建和部署脚本。它有两个版本:Windows 内置的 Windows PowerShell 5.1,以及开源并可运行在 Windows、Linux 和 macOS 上的 PowerShell 7 及更高版本(命令名为 pwsh)。本教程以 PowerShell 7 为准。
安装 PowerShell 并运行 Hello, world
在 Windows 上,用 winget install --id Microsoft.PowerShell --source winget 安装 PowerShell 7;在 macOS 和 Linux 上,使用 Homebrew 或微软安装指南中介绍的包管理器。脚本是扩展名为 .ps1 的文本文件。
# hello.ps1
Write-Output "Hello, world!"pwsh ./hello.ps1
# Hello, world!在 Windows 上,执行策略可能会阻止脚本运行。Set-ExecutionPolicy -Scope CurrentUser RemoteSigned 允许运行你自己的本地脚本,同时仍要求下载的脚本必须签名。推荐使用安装了 PowerShell 扩展的 Visual Studio Code 作为编辑器。
Cmdlet 与管道
命令称为 cmdlet,遵循「动词-名词」的命名模式,如 Get-Process、Set-Location 或 New-Item。有三个 cmdlet 能帮你探索其他一切:Get-Command、Get-Help 和 Get-Member。
Get-Command -Noun Process # list commands that work with processes
Get-Help Get-ChildItem -Examples # show usage examples
# five processes using the most memory
Get-Process |
Sort-Object -Property WorkingSet64 -Descending |
Select-Object -First 5 -Property Name, Id, WorkingSet64
# files larger than 1 MB in the current folder
Get-ChildItem -File | Where-Object { $_.Length -gt 1MB } |
ForEach-Object { "{0} {1:N0} KB" -f $_.Name, ($_.Length / 1KB) }
Get-Date | Get-Member -MemberType Property # inspect an object在脚本块内,$_(或 $PSItem)是管道中的当前对象。由于对象保留了类型,Sort-Object 无需额外处理就能按数值排序数字、按时间顺序排序日期。
变量与类型
变量以 $ 开头。它们可以保存任何 .NET 对象,你也可以用方括号添加类型约束。双引号字符串会展开变量和 $( ) 表达式;单引号字符串则是字面文本。
$name = "Ada"
[int]$count = 3
$price = 19.99 # System.Double
$isAdmin = $false
$today = Get-Date
"Hello, $name" # Hello, Ada
"Next: $($count + 1)" # Next: 4
'No $expansion here' # No $expansion here
$price.GetType().Name # Double
$today.ToString("yyyy-MM-dd") # for example 2026-10-31
[int]"42" + 1 # 43 (explicit conversion)| 类型 | 示例 | 说明 |
|---|---|---|
[int] | 42 | 32 位整数 |
[double] | 3.14 | 浮点数;金额请使用 [decimal] |
[string] | "text" | 默认不区分大小写的比较 |
[bool] | $true, $false | 自动变量,不是关键字 |
[datetime] | Get-Date | 完整的 .NET DateTime 对象 |
[array], [hashtable] | @(1, 2), @{ a = 1 } | 集合,下文介绍 |
运算符与流程控制
比较运算符是单词而不是符号:-eq、-ne、-gt、-lt、-ge、-le、-like(通配符)、-match(正则表达式)和 -contains。字符串比较默认不区分大小写,除非使用 -ceq 这类以 c 开头的版本。
$temp = 22
if ($temp -gt 30) {
"hot"
} elseif ($temp -ge 15) {
"mild" # mild
} else {
"cold"
}
switch ("report.csv") {
{ $_ -like "*.csv" } { "CSV file" } # CSV file
{ $_ -like "*.txt" } { "text file" }
default { "other" }
}
foreach ($n in 1..3) { "n = $n" } # n = 1, n = 2, n = 3
for ($i = 0; $i -lt 2; $i++) { "i = $i" } # i = 0, i = 1
$k = 3
while ($k -gt 0) { $k-- }
"Hello" -eq "hello" # True函数与参数
函数使用 param() 块声明带类型的具名参数。加上 [CmdletBinding()] 后,函数会获得与内置 cmdlet 相同的通用参数,如 -Verbose。任何未被捕获的输出都会成为函数的返回值。
function Get-Greeting {
[CmdletBinding()]
param(
[Parameter(Mandatory)]
[string]$Name,
[string]$Greeting = "Hello"
)
Write-Verbose "Building greeting for $Name"
"$Greeting, $Name!"
}
Get-Greeting -Name "Ann" # Hello, Ann!
Get-Greeting -Name "Bo" -Greeting "Hi" # Hi, Bo!
Get-Greeting "Cy" -Verbose # also prints the verbose message像调用 cmdlet 一样调用函数,参数之间用空格分隔:Get-Greeting -Name Ann。写成 Get-Greeting("Ann", "Hi") 会传入单个数组参数,这常让从其他语言转来的人感到意外。
数组、哈希表与自定义对象
数组用 @( ) 或逗号分隔的列表创建。哈希表写作 @{ },存储键值对。[pscustomobject] 可把哈希表转换为对象,与 Sort-Object、Format-Table 和 Export-Csv 配合良好。
$langs = @("PowerShell", "Python")
$langs += "Go" # creates a new, longer array
$langs.Count # 3
$langs[0] # PowerShell
$langs -contains "Go" # True
$ports = @{ http = 80; https = 443 }
$ports["ssh"] = 22
$ports.https # 443
$ports.Keys.Count # 3
$user = [pscustomobject]@{ Name = "Ann"; Age = 31 }
$user.Name # Ann
$people = @(
[pscustomobject]@{ Name = "Bo"; Age = 25 }
$user
)
$people | Sort-Object Age | Format-Table用 += 向数组追加元素,每次都会复制整个数组。对于大循环,请直接收集循环输出($result = foreach (...) { ... }),或使用 [System.Collections.Generic.List[object]]。
错误处理
PowerShell 有会中止执行的终止错误,以及只打印消息并继续执行的非终止错误。try/catch/finally 只能捕获终止错误,所以想捕获某个 cmdlet 的失败时,要给它加上 -ErrorAction Stop。
try {
$content = Get-Content -Path "missing.txt" -ErrorAction Stop
}
catch [System.Management.Automation.ItemNotFoundException] {
Write-Warning "File not found: $($_.Exception.Message)"
}
catch {
Write-Error "Unexpected error: $_"
}
finally {
"cleanup done"
}
$ErrorActionPreference = "Stop" # make all errors terminating in this script
throw "Something went wrong" # raise your own terminating error在 catch 内,$_ 是错误记录。在脚本顶部设置 $ErrorActionPreference = "Stop" 是实现快速失败的常用做法。
一个完整的小脚本:磁盘占用报告
这个脚本列出某个文件夹下最大的文件,按扩展名分组,并导出 CSV 报告。它综合运用了参数、管道、计算属性和错误处理。
# report.ps1
param(
[string]$Path = ".",
[int]$Top = 5
)
$ErrorActionPreference = "Stop"
$files = Get-ChildItem -Path $Path -File -Recurse
"Largest $Top files:"
$files | Sort-Object Length -Descending | Select-Object -First $Top |
Format-Table Name, @{ Name = "SizeKB"; Expression = { [math]::Round($_.Length / 1KB, 1) } }
$byExt = $files | Group-Object Extension | ForEach-Object {
[pscustomobject]@{
Extension = if ($_.Name) { $_.Name } else { "(none)" }
Files = $_.Count
TotalMB = [math]::Round(($_.Group | Measure-Object Length -Sum).Sum / 1MB, 2)
}
} | Sort-Object TotalMB -Descending
$byExt | Format-Table
$byExt | Export-Csv -Path "usage.csv" -NoTypeInformation
"Report saved to usage.csv"pwsh ./report.ps1 -Path ~/Documents -Top 3接下来学什么
- Microsoft Learn 上的 PowerShell 101 和 PowerShell 文档。
- 在 Shell 中使用
Get-Help about_*,例如Get-Help about_Operators;请先运行Update-Help。 - PowerShell Gallery,官方模块仓库,配合
Install-Module使用。 - PSScriptAnalyzer:一款按推荐实践检查脚本的 lint 工具。
常见问题
PowerShell 和 Windows PowerShell 有什么区别?
Windows PowerShell 5.1 是 Windows 内置的旧版本,基于 .NET Framework。PowerShell 7 及更高版本是基于现代 .NET 的跨平台开源版本,用 pwsh 命令启动。
PowerShell 和命令提示符是一回事吗?
不是。命令提示符(cmd.exe)运行批处理命令并传递文本。PowerShell 是完整的脚本语言,传递的是对象,不过它同样可以运行大多数命令行程序。
PowerShell 能在 Linux 和 macOS 上运行吗?
可以。PowerShell 7 及更高版本可运行在 Windows、Linux 和 macOS 上,但一些 Windows 专用的模块只能在 Windows 上使用。
为什么我的 .ps1 脚本无法运行?
可能是 Windows 的执行策略阻止了它。运行 Set-ExecutionPolicy -Scope CurrentUser RemoteSigned,并用路径启动脚本,如 ./script.ps1。
PowerShell 中的 $_ 是什么意思?
$_(也写作 $PSItem)是管道中的当前对象,用于 Where-Object 和 ForEach-Object 等 cmdlet 的脚本块内;在 catch 内则表示当前的错误。