[玩转系统] 实用 PowerShell:分支
作者:精品下载站 日期:2024-12-14 04:13:58 浏览:14 分类:玩电脑
实用 PowerShell:分支
在实用 PowerShell 系列的上一篇文章中,我讨论了循环作为流控制的一部分。在本文中,我将介绍流程控制的另一个重要部分:分支。根据条件,分支定义了代码要遵循的多个路径。
如果-那么-否则
除了循环结构之外,还有用于控制代码分支的决策 cmdlet。它是一个基本的构造,允许您根据满足的条件(if)(then)和可选的不满足的条件(else)来分支代码。这种结构很容易理解和使用,因为它遵循自然语言。您还会在其他环境中看到它,例如家庭自动化或 PowerAutomate。在下面的示例中,我们将处理禁用尚未禁用的共享邮箱帐户的邮箱:
$Mailboxes= Get-ExoMailbox -ResultSize Unlimited -Properties AccountDisabled
ForEach( $Mailbox in $Mailboxes) {
If( $Mailbox.RecipientTypeDetails -ieq 'SharedMailbox') {
If(-not $Mailbox.AccountDisabled) {
Write-Host( 'Disabling account of shared mailbox {0}' -f $Mailbox.userPrincipalName)
}
Else {
Write-Host( 'Account of shared mailbox {0} already disabled' -f $Mailbox.userPrincipalName)
}
}
Else {
Write-Host ('{0} is not a shared mailbox' -f $Mailbox.userPrincipalName)
}
}
请注意,比较运算符 ieq 代表不区分大小写的相等。这是 eq 的默认模式,但为了清楚起见,我习惯性地提及它。
如示例所示,您可以嵌套 If cmdlet,Else 部分是可选的,但通常作为占位符添加,并带有描述性注释以供参考。当条件变得复杂时,保持概览就成为一项挑战,并且您可能会不匹配括号或引号。这就是 Visual Studio Code 甚至 PowerShell ISE 等编辑器发挥作用的地方,当鼠标悬停在括号上时,指示(当前)匹配括号的位置,从而更容易发现丢失的左括号或右括号或引号。 Visual Studio Code 还允许您折叠(或展开)if 或 else 分支,如图 1 所示。
转变
正如您在 If-Then-Else 示例中看到的那样,当使用多个条件或嵌套时,代码可能会变得非常复杂并且不可读。这就是 Switch 结构派上用场的地方。 Switch 结构允许你改变这个:
If( $Mailbox.recipientTypeDetails -ieq 'UserMailbox') {
# code for UserMailbox
ElseIf( $Mailbox.recipientTypeDetails -ieq 'SharedMailbox') {
# code for SharedMailbox
Else {
# code for not UserMailbox nor SharedMailbox
}
进入这个:
Switch( $Mailbox.recipientTypeDetails) {
'UserMailbox' {
# code for UserMailbox
}
'SharedMailbox' {
# code for SharedMailbox
}
default {
# code for not UserMailbox nor SharedMailbox
Write-Warning ('Unsupported type: {0}' -f $_)
}
}
$Mailbox.recipientTypeDetails 值根据“UserMailbox”和“SharedMailbox”进行检查。当找到匹配项时,将运行相应的脚本块。如果未找到匹配项,则执行可选的默认代码。变量 $_ 被分配了在开关内匹配的值,我们用它来报告我们遇到了不受支持的recipientTypeDetails属性值。
Switch 还有一些操作修饰符,例如开关 -regex 和 -wildcard。这些允许 Switch 根据正则表达式或通配符(类似于 -like)检查评估的对象。请注意,原则上每个条件都会被评估,这可能会导致多个脚本块被执行。例如,在以下显示通配符模式下 Switch 的片段中,当recipientTypeDetails 为 UserMailbox 时,UserMailbox 和 *Mailbox 的代码都将运行:
Switch -wildcard ( $Mailbox.recipientTypeDetails) {
'UserMailbox' {
# code for UserMailbox
}
'*Mailbox' {
# code for any type ending in Mailbox
}
}
可以通过在代码块末尾添加中断来避免进一步评估,例如
Switch -wildcard ( $Mailbox.recipientTypeDetails) {
'UserMailbox' {
# code for UserMailbox
break
}
'*Mailbox' {
# code for any type ending in Mailbox
break
}
}
Switch cmdlet 功能强大,可以防止代码陷入过于复杂的 if-then-else 分支,同时保持可读性。例如,它还允许您匹配多个值。有关开关和其他用法的更多信息,请参阅此处。
停止 Cmdlet
到目前为止,我们已经看到了按顺序执行代码的结构。在某些情况下,您可能想要缩短分支或跳过迭代。例如,当您循环遍历元素以查找匹配项时,找到匹配项后无需继续循环的其余部分。这时可以使用Break。另一方面,如果您不想处理循环中的某个元素,则可以使用Continue。
与 Break 一样,停止 cmdlet 也可在函数和脚本级别使用,其形式为“Exit”和“Return”。 Exit 在调用函数或脚本的范围内终止该函数或脚本。 Return 退出脚本或函数,可选择将对象返回到调用它的范围,之后将继续执行。要了解这些 cmdlet 的不同效果,请查看以下示例:
Function Test {
For( $i=0; $i -lt 4; $i++) {
Write-Host ('Start {0}' -f $i)
If( $i -eq 2) {
# Aborts the loop
Break
# Skips iteration, continues with next iteration
Continue
# Aborts execution, continues at caller scope
Return
# Exits and at scope of caller
Exit
}
Write-Host ('End {0}' -f $i)
}
Write-Host ('End Function.')
}
Test
Write-Host ('End Script.')
可以通过对上面脚本中未测试的 cmdlet 进行注释来演示使用每个停止 cmdlet 的效果。下表显示了每个未注释的停止 cmdlet 的输出。
BreakContinueReturnExitStart 0End 0
Start 1
End 1
Start 2
End Function.
End Script.Start 0
End 0
Start 1
End 1
Start 2
Start 3
End 3
End Function.
End Script.Start 0
End 0
Start 1
End 1
Start 2
End Script.Start 0
End 0
Start 1
End 1
Start 2
毕竟,现在我强烈建议避免停止 cmdlet,而是对循环或函数使用单点退出。那些支持使用停止 cmdlet 的人通常声称它们可以提高效率和性能。虽然对于非结构化代码可能确实如此,但当您正确构建代码时,就没有真正需要添加停止 cmdlet。此外,停止 cmdlet 会使代码更难以阅读和理解。许多组织使用代码风格指南,强制使用单一退出点。
一元运算符
在一些示例中,我使用一元运算符。一元运算符允许您编写 $i++ 而不是 $i=$i+1。您还可以通过编写 ++$i 在评估变量之前添加一元运算符,在这种情况下,在评估变量之前将 1 添加到 $i 中。您可以使用“-”进行减法,例如 $i-。您还可以使用一元运算符来执行其他算术运算,例如$i+=2 会将 2 添加到 $i,$i*=4 会将 $i 中存储的值乘以 4。有关一元运算符的更多信息,请参阅此处。
一元运算符的常见用法是字符串连接或将项目“添加”到数组或对象集合中,例如 $string+= $field 或 $array+= $item。然而,在幕后,此代码执行为 $array= $array + $item,它复制 $array 对象并添加 $item。这不仅对于较大的复杂对象来说可能会很慢。它还解释了为什么这适用于数组,根据定义,数组具有固定数量的元素(以及为什么我提到使用引号“添加”)。
字符串或数组等对象类型有更好的替代 (.NET) 对象类型,它们更适合密集型数据操作,例如用 [System.Collections.ArrayList] 代替 Array,或用 [System.Text.StringBuilder] 代替字符串。这是一个快速比较,以便您了解:
# Add 10.000 numbers to an array
PS> $Array= @()
PS> Measure-Command {
1..10000 | ForEach{ $Array+= $_ }
} | Select TotalMilliseconds
TotalMilliseconds
-----------------
21746.56
# Add 10.000 numbers to arraylist
PS> $ArrayList= [System.Collections.ArrayList]::new()
PS> Measure-Command {
1..10000 | ForEach{ $ArrayList.Add( $_)| Out-Null }
} | Select TotalMilliseconds
TotalMilliseconds
-----------------
77.69
运行上面的示例,您会注意到,在使用其内置的 Add 方法时,ArrayList 明显比使用 Array 快。请注意,ArrayList 的 Add 返回刚刚添加的元素的编号,因此我在示例中通过将输出管道传输到 Out-Null 来抑制该情况。现在,我并不是说您需要更改所有代码,但对于处理较大数据集的脚本来说,性能优势是相当可观的。
动态执行的分支
与循环一样,分支是基本编程结构之一。它为您的代码添加了动态性,让您的代码根据条件决定执行什么。此外,当嵌套的 if-then-else 语句变得过于复杂时,熟悉 switch cmdlet 将有所帮助,并让您保持可读性和可维护性。
如果您有疑问或意见,请随时在评论中联系。如果没有的话,直到下一篇文章!
猜你还喜欢
- 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