[玩转系统] 关于 switch 语句你想知道的一切
作者:精品下载站 日期:2024-12-14 03:04:14 浏览:12 分类:玩电脑
关于 switch 语句你想知道的一切
与许多其他语言一样,PowerShell 具有用于控制脚本内执行流程的命令。这些语句之一是 switch 语句,在 PowerShell 中,它提供了其他语言中没有的功能。今天,我们深入探讨 PowerShell switch
的使用。
笔记
本文的原始版本出现在@KevinMarquette 撰写的博客上。 PowerShell 团队感谢 Kevin 与我们分享这些内容。请查看他的博客:PowerShellExplained.com。
if
语句
您学习的第一个语句是 if
语句。如果语句为 $true
,它允许您执行脚本块。
if ( Test-Path $Path )
{
Remove-Item $Path
}
您可以使用 elseif
和 else
语句获得更复杂的逻辑。这是一个示例,其中我有一个星期几的数值,并且我想获取字符串形式的名称。
$day = 3
if ( $day -eq 0 ) { $result = 'Sunday' }
elseif ( $day -eq 1 ) { $result = 'Monday' }
elseif ( $day -eq 2 ) { $result = 'Tuesday' }
elseif ( $day -eq 3 ) { $result = 'Wednesday' }
elseif ( $day -eq 4 ) { $result = 'Thursday' }
elseif ( $day -eq 5 ) { $result = 'Friday' }
elseif ( $day -eq 6 ) { $result = 'Saturday' }
$result
Wednesday
事实证明,这是一种常见的模式,并且有很多方法可以解决这个问题。其中之一是带有开关
。
switch语句
switch
语句允许您提供变量和可能值的列表。如果值与变量匹配,则执行其脚本块。
$day = 3
switch ( $day )
{
0 { $result = 'Sunday' }
1 { $result = 'Monday' }
2 { $result = 'Tuesday' }
3 { $result = 'Wednesday' }
4 { $result = 'Thursday' }
5 { $result = 'Friday' }
6 { $result = 'Saturday' }
}
$result
'Wednesday'
对于本示例,$day
的值与其中一个数值匹配,然后将正确的名称分配给 $result
。在本示例中,我们仅进行变量赋值,但任何 PowerShell 都可以在这些脚本块中执行。
分配给变量
我们可以用另一种方式编写最后一个例子。
$result = switch ( $day )
{
0 { 'Sunday' }
1 { 'Monday' }
2 { 'Tuesday' }
3 { 'Wednesday' }
4 { 'Thursday' }
5 { 'Friday' }
6 { 'Saturday' }
}
我们将该值放置在 PowerShell 管道上并将其分配给 $result
。您可以使用 if
和 foreach
语句执行相同的操作。
默认
我们可以使用 default
关键字来确定如果没有匹配项会发生什么。
$result = switch ( $day )
{
0 { 'Sunday' }
# ...
6 { 'Saturday' }
default { 'Unknown' }
}
这里我们在默认情况下返回值Unknown
。
弦乐
我在最后的示例中匹配数字,但您也可以匹配字符串。
$item = 'Role'
switch ( $item )
{
Component
{
'is a component'
}
Role
{
'is a role'
}
Location
{
'is a location'
}
}
is a role
我决定不在此处将 Component
、Role
和 Location
匹配项用引号引起来,以强调它们是可选的。在大多数情况下,switch
将它们视为字符串。
数组
PowerShell switch
的一项很酷的功能是它处理数组的方式。如果您为 switch
提供一个数组,它会处理该集合中的每个元素。
$roles = @('WEB','Database')
switch ( $roles ) {
'Database' { 'Configure SQL' }
'WEB' { 'Configure IIS' }
'FileServer' { 'Configure Share' }
}
Configure IIS
Configure SQL
如果数组中有重复的项目,那么它们会被相应的部分多次匹配。
PS项目
您可以使用 $PSItem
或 $_
来引用已处理的当前项目。当我们进行简单匹配时,$PSItem
就是我们要匹配的值。我将在下一节中使用此变量执行一些高级匹配。
参数
PowerShell switch
的一个独特功能是它具有许多可以更改其执行方式的开关参数。
-CaseSensitive
默认情况下,匹配不区分大小写。如果需要区分大小写,可以使用-CaseSensitive
。这可以与其他开关参数结合使用。
-Wildcard
我们可以使用 -wildcard
开关启用通配符支持。这使用与 -like
运算符相同的通配符逻辑来进行每次匹配。
$Message = 'Warning, out of disk space'
switch -Wildcard ( $message )
{
'Error*'
{
Write-Error -Message $Message
}
'Warning*'
{
Write-Warning -Message $Message
}
default
{
Write-Information $message
}
}
WARNING: Warning, out of disk space
在这里,我们正在处理一条消息,然后根据内容将其输出到不同的流上。
-Regex
switch 语句支持正则表达式匹配,就像它支持通配符一样。
switch -Regex ( $message )
{
'^Error'
{
Write-Error -Message $Message
}
'^Warning'
{
Write-Warning -Message $Message
}
default
{
Write-Information $message
}
}
我在另一篇文章中提供了更多使用正则表达式的示例:使用正则表达式的多种方法。
-File
switch 语句的一个鲜为人知的功能是它可以使用 -File
参数处理文件。您可以将 -file
与文件路径一起使用,而不是为其提供变量表达式。
switch -Wildcard -File $path
{
'Error*'
{
Write-Error -Message $PSItem
}
'Warning*'
{
Write-Warning -Message $PSItem
}
default
{
Write-Output $PSItem
}
}
它的工作原理就像处理数组一样。在此示例中,我将其与通配符匹配结合起来并使用 $PSItem
。这将处理日志文件并根据正则表达式匹配将其转换为警告和错误消息。
高级细节
现在您已经了解了所有这些记录的功能,我们可以在更高级的处理环境中使用它们。
表达式
switch
可以位于表达式而不是变量上。
switch ( ( Get-Service | Where status -eq 'running' ).name ) {...}
无论表达式的计算结果是什么,都是用于匹配的值。
多场比赛
您可能已经了解了这一点,但是 switch
可以匹配多个条件。使用 -wildcard
或 -regex
匹配时尤其如此。您可以多次添加相同的条件,并且所有条件都会被触发。
switch ( 'Word' )
{
'word' { 'lower case word match' }
'Word' { 'mixed case word match' }
'WORD' { 'upper case word match' }
}
lower case word match
mixed case word match
upper case word match
这三项声明均被驳回。这表明每个条件都被检查(按顺序)。这对于处理数组来说是正确的,其中每个项目检查每个条件。
继续
通常,这是我引入 break
语句的地方,但我们最好先学习如何使用 continue
。就像 foreach
循环一样,continue
继续到集合中的下一个项目,或者如果没有更多项目,则退出 switch
。我们可以使用 continue 语句重写最后一个示例,以便只执行一个语句。
switch ( 'Word' )
{
'word'
{
'lower case word match'
continue
}
'Word'
{
'mixed case word match'
continue
}
'WORD'
{
'upper case word match'
continue
}
}
lower case word match
不是匹配所有三个项目,而是匹配第一个项目,然后继续切换到下一个值。由于没有剩余值可供处理,因此切换退出。下一个示例显示通配符如何匹配多个项目。
switch -Wildcard -File $path
{
'*Error*'
{
Write-Error -Message $PSItem
continue
}
'*Warning*'
{
Write-Warning -Message $PSItem
continue
}
default
{
Write-Output $PSItem
}
}
由于输入文件中的一行可能同时包含单词 Error
和 Warning
,因此我们只希望执行第一个,然后继续处理文件。
休息
break
语句退出开关。这与 continue
为单个值呈现的行为相同。处理数组时会显示出差异。 break
停止开关中的所有处理,continue
移动到下一个项目。
$Messages = @(
'Downloading update'
'Ran into errors downloading file'
'Error: out of disk space'
'Sending email'
'...'
)
switch -Wildcard ($Messages)
{
'Error*'
{
Write-Error -Message $PSItem
break
}
'*Error*'
{
Write-Warning -Message $PSItem
continue
}
'*Warning*'
{
Write-Warning -Message $PSItem
continue
}
default
{
Write-Output $PSItem
}
}
Downloading update
WARNING: Ran into errors downloading file
write-error -message $PSItem : Error: out of disk space
+ CategoryInfo : NotSpecified: (:) [Write-Error], WriteErrorException
+ FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException
在这种情况下,如果我们点击任何以 Error
开头的行,则会收到错误并且开关停止。这就是 break
语句为我们所做的事情。如果我们在字符串中发现 Error
而不仅仅是在开头,我们会将其写为警告。我们对警告
做同样的事情。一行可能同时包含单词 Error
和 Warning
,但我们只需要处理一个。这就是 continue
语句为我们所做的事情。
打破标签
switch
语句支持 break/continue
标签,就像 foreach
一样。
:filelist foreach($path in $logs)
{
:logFile switch -Wildcard -File $path
{
'Error*'
{
Write-Error -Message $PSItem
break filelist
}
'Warning*'
{
Write-Error -Message $PSItem
break logFile
}
default
{
Write-Output $PSItem
}
}
}
我个人不喜欢使用中断标签,但我想指出它们,因为如果您以前从未见过它们,它们会让人感到困惑。当您有多个嵌套的 switch
或 foreach
语句时,您可能想要突破最里面的项目。您可以在可以作为中断
目标的开关
上放置一个标签。
枚举
PowerShell 5.0 为我们提供了枚举,我们可以在 switch 中使用它们。
enum Context {
Component
Role
Location
}
$item = [Context]::Role
switch ( $item )
{
Component
{
'is a component'
}
Role
{
'is a role'
}
Location
{
'is a location'
}
}
is a role
如果您想将所有内容保留为强类型枚举,则可以将它们放在括号中。
switch ($item )
{
([Context]::Component)
{
'is a component'
}
([Context]::Role)
{
'is a role'
}
([Context]::Location)
{
'is a location'
}
}
这里需要括号,以便开关不会将值 [Context]::Location
视为文字字符串。
ScriptBlock
如果需要,我们可以使用脚本块来执行匹配评估。
$age = 37
switch ( $age )
{
{$PSItem -le 18}
{
'child'
}
{$PSItem -gt 18}
{
'adult'
}
}
'adult'
这会增加复杂性,并使您的 switch
难以阅读。在大多数情况下,如果您要使用类似的内容,最好使用 if
和 elseif
语句。如果我已经有一个大型开关并且我需要两个项目来达到相同的评估块,我会考虑使用它。
我认为有助于提高可读性的一件事是将脚本块放在括号中。
switch ( $age )
{
({$PSItem -le 18})
{
'child'
}
({$PSItem -gt 18})
{
'adult'
}
}
它仍然以相同的方式执行,并且在快速查看时提供更好的视觉休息。
正则表达式$匹配
我们需要重新审视正则表达式来触及一些不太明显的东西。使用正则表达式填充 $matches
变量。当我谈论使用正则表达式的多种方法时,我确实更多地讨论了 $matches
的使用。这是一个快速示例,展示了它与命名匹配的实际操作。
$message = 'my ssn is 123-23-3456 and credit card: 1234-5678-1234-5678'
switch -regex ($message)
{
'(?<SSN>\d\d\d-\d\d-\d\d\d\d)'
{
Write-Warning "message contains a SSN: $($matches.SSN)"
}
'(?<CC>\d\d\d\d-\d\d\d\d-\d\d\d\d-\d\d\d\d)'
{
Write-Warning "message contains a credit card number: $($matches.CC)"
}
'(?<Phone>\d\d\d-\d\d\d-\d\d\d\d)'
{
Write-Warning "message contains a phone number: $($matches.Phone)"
}
}
WARNING: message may contain a SSN: 123-23-3456
WARNING: message may contain a credit card number: 1234-5678-1234-5678
$null
您可以匹配一个不必是默认值的 $null
值。
$values = '', 5, $null
switch ( $values )
{
$null { "Value '$_' is `$null" }
{ '' -eq $_ } { "Value '$_' is an empty string" }
default { "Value [$_] isn't an empty string or `$null" }
}
Value '' is an empty string
Value [5] isn't an empty string or $null
Value '' is $null
在 switch
语句中测试空字符串时,使用本示例中所示的比较语句而不是原始值 ''
非常重要。在 switch
语句中,原始值 ''
也匹配 $null
。例如:
$values = '', 5, $null
switch ( $values )
{
$null { "Value '$_' is `$null" }
'' { "Value '$_' is an empty string" }
default { "Value [$_] isn't an empty string or `$null" }
}
Value '' is an empty string
Value [5] isn't an empty string or $null
Value '' is $null
Value '' is an empty string
另外,请小心 cmdlet 的空返回。没有输出的 Cmdlet 或管道将被视为与任何内容都不匹配的空数组,包括 default
情况。
$file = Get-ChildItem NonExistantFile*
switch ( $file )
{
$null { '$file is $null' }
default { "`$file is type $($file.GetType().Name)" }
}
# No matches
常数表达式
Lee Dailey 指出,我们可以使用常量 $true
表达式来计算 [bool]
项。想象一下,如果我们需要进行多次布尔检查。
$isVisible = $false
$isEnabled = $true
$isSecure = $true
switch ( $true )
{
$isEnabled
{
'Do-Action'
}
$isVisible
{
'Show-Animation'
}
$isSecure
{
'Enable-AdminMenu'
}
}
Do-Action
Enabled-AdminMenu
这是一种评估多个布尔字段的状态并对其采取行动的简洁方法。这样做的一个很酷的事情是,您可以通过一次匹配来翻转尚未评估的值的状态。
$isVisible = $false
$isEnabled = $true
$isAdmin = $false
switch ( $true )
{
$isEnabled
{
'Do-Action'
$isVisible = $true
}
$isVisible
{
'Show-Animation'
}
$isAdmin
{
'Enable-AdminMenu'
}
}
Do-Action
Show-Animation
在此示例中将 $isEnabled
设置为 $true
可确保 $isVisible
也设置为 $true
。然后,当 $isVisible
被求值时,它的脚本块被调用。这有点违反直觉,但却是对机制的巧妙利用。
$switch 自动变量
当 switch
处理其值时,它会创建一个枚举器并调用它 $switch
。这是由 PowerShell 创建的自动变量,您可以直接操作它。
$a = 1, 2, 3, 4
switch($a) {
1 { [void]$switch.MoveNext(); $switch.Current }
3 { [void]$switch.MoveNext(); $switch.Current }
}
这将为您提供以下结果:
2
4
通过向前移动枚举器,switch
不会处理下一项,但您可以直接访问该值。我会称之为疯狂。
其他图案
哈希表
我最受欢迎的帖子之一是我在哈希表上发表的帖子。哈希表的用例之一是用作查找表。这是 switch 语句经常处理的常见模式的另一种方法。
$day = 3
$lookup = @{
0 = 'Sunday'
1 = 'Monday'
2 = 'Tuesday'
3 = 'Wednesday'
4 = 'Thursday'
5 = 'Friday'
6 = 'Saturday'
}
$lookup[$day]
Wednesday
如果我仅使用 switch
作为查找,我通常会使用 hashtable
来代替。
枚举
PowerShell 5.0 引入了 Enum
,在这种情况下它也是一个选项。
$day = 3
enum DayOfTheWeek {
Sunday
Monday
Tuesday
Wednesday
Thursday
Friday
Saturday
}
[DayOfTheWeek]$day
Wednesday
我们可以花一整天的时间寻找解决这个问题的不同方法。我只是想确保你知道你有选择。
最后的话
switch 语句表面上很简单,但它提供了一些大多数人没有意识到的高级功能。将这些功能结合在一起使其成为一个强大的功能。我希望你学到了一些你以前没有意识到的东西。
猜你还喜欢
- 03-30 [玩转系统] 如何用批处理实现关机,注销,重启和锁定计算机
- 02-14 [系统故障] Win10下报错:该文件没有与之关联的应用来执行该操作
- 01-07 [系统问题] Win10--解决锁屏后会断网的问题
- 01-02 [系统技巧] Windows系统如何关闭防火墙保姆式教程,超详细
- 12-15 [玩转系统] 如何在 Windows 10 和 11 上允许多个 RDP 会话
- 12-15 [玩转系统] 查找 Exchange/Microsoft 365 中不活动(未使用)的通讯组列表
- 12-15 [玩转系统] 如何在 Windows 上安装远程服务器管理工具 (RSAT)
- 12-15 [玩转系统] 如何在 Windows 上重置组策略设置
- 12-15 [玩转系统] 如何获取计算机上的本地管理员列表?
- 12-15 [玩转系统] 在 Visual Studio Code 中连接到 MS SQL Server 数据库
- 12-15 [玩转系统] 如何降级 Windows Server 版本或许可证
- 12-15 [玩转系统] 如何允许非管理员用户在 Windows 中启动/停止服务
取消回复欢迎 你 发表评论:
- 精品推荐!
-
- 最新文章
- 热门文章
- 热评文章
[影视] 黑道中人 Alto Knights(2025)剧情 犯罪 历史 电影
[古装剧] [七侠五义][全75集][WEB-MP4/76G][国语无字][1080P][焦恩俊经典]
[实用软件] 虚拟手机号 电话 验证码 注册
[电视剧] 安眠书店/你 第五季 You Season 5 (2025) 【全10集】
[电视剧] 棋士(2025) 4K 1080P【全22集】悬疑 犯罪 王宝强 陈明昊
[软件合集] 25年6月5日 精选软件22个
[软件合集] 25年6月4日 精选软件36个
[短剧] 2025年06月04日 精选+付费短剧推荐33部
[短剧] 2025年06月03日 精选+付费短剧推荐25部
[软件合集] 25年6月3日 精选软件44个
[剧集] [央视][笑傲江湖][2001][DVD-RMVB][高清][40集全]李亚鹏、许晴、苗乙乙
[电视剧] 欢乐颂.5部全 (2016-2024)
[电视剧] [突围] [45集全] [WEB-MP4/每集1.5GB] [国语/内嵌中文字幕] [4K-2160P] [无水印]
[影视] 【稀有资源】香港老片 艺坛照妖镜之96应召名册 (1996)
[剧集] 神经风云(2023)(完结).4K
[剧集] [BT] [TVB] [黑夜彩虹(2003)] [全21集] [粤语中字] [TV-RMVB]
[实用软件] 虚拟手机号 电话 验证码 注册
[资源] B站充电视频合集,包含多位重量级up主,全是大佬真金白银买来的~【99GB】
[影视] 内地绝版高清录像带 [mpg]
[书籍] 古今奇书禁书三教九流资料大合集 猎奇必备珍藏资源PDF版 1.14G
[电视剧] [突围] [45集全] [WEB-MP4/每集1.5GB] [国语/内嵌中文字幕] [4K-2160P] [无水印]
[剧集] [央视][笑傲江湖][2001][DVD-RMVB][高清][40集全]李亚鹏、许晴、苗乙乙
[电影] 美国队长4 4K原盘REMUX 杜比视界 内封简繁英双语字幕 49G
[电影] 死神来了(1-6)大合集!
[软件合集] 25年05月13日 精选软件16个
[精品软件] 25年05月15日 精选软件18个
[绝版资源] 南与北 第1-2季 合集 North and South (1985) /美国/豆瓣: 8.8[1080P][中文字幕]
[软件] 25年05月14日 精选软件57个
[短剧] 2025年05月14日 精选+付费短剧推荐39部
[短剧] 2025年05月15日 精选+付费短剧推荐36部
- 最新评论
-
- 热门tag