[玩转系统] 关于 if 语句你想知道的一切
作者:精品下载站 日期:2024-12-14 03:04:20 浏览:14 分类:玩电脑
关于 if 语句你想知道的一切
与许多其他语言一样,PowerShell 具有用于在脚本中条件执行代码的语句。这些语句之一是 If 语句。今天我们将深入探讨 PowerShell 中最基本的命令之一。
笔记
本文的原始版本出现在@KevinMarquette 撰写的博客上。 PowerShell 团队感谢 Kevin 与我们分享这些内容。请查看他的博客:PowerShellExplained.com。
有条件执行
您的脚本通常需要做出决策并根据这些决策执行不同的逻辑。这就是我所说的条件执行的意思。您需要评估一个语句或值,然后根据该评估执行不同的代码部分。这正是 if
语句的作用。
if
语句
以下是 if
语句的基本示例:
$condition = $true
if ( $condition )
{
Write-Output "The condition was true"
}
if
语句所做的第一件事是计算括号中的表达式。如果其计算结果为 $true
,则执行大括号中的 scriptblock
。如果值为 $false
,那么它将跳过该脚本块。
在前面的示例中,if
语句只是评估 $condition
变量。它是 $true
并且会在脚本块内执行 Write-Output
命令。
在某些语言中,您可以在 if
语句后面放置一行代码,然后它就会被执行。 PowerShell 中的情况并非如此。您必须提供完整的带有大括号的 scriptblock
才能正常工作。
比较运算符
if
语句最常见的用途是将两个项目相互比较。 PowerShell 有针对不同比较场景的特殊运算符。使用比较运算符时,会将左侧的值与右侧的值进行比较。
-eq 表示平等
-eq
在两个值之间进行相等性检查,以确保它们彼此相等。
$value = Get-MysteryValue
if ( 5 -eq $value )
{
# do something
}
在此示例中,我采用已知值 5
并将其与我的 $value
进行比较,看看它们是否匹配。
一种可能的用例是在对某个值采取操作之前检查该值的状态。您可以获取一个服务并在调用 Restart-Service
之前检查其状态是否正在运行。
在 C# 等其他语言中,通常使用 ==
来表示相等(例如:5 == $value
),但这不适用于 PowerShell。人们犯的另一个常见错误是使用等号(例如:5=$value
),该等号是为变量赋值而保留的。通过将你的已知值放在左边,会让这个错误更难犯。
该运算符(和其他运算符)有一些变化。
-eq
不区分大小写的相等-ieq
不区分大小写的相等-ceq
区分大小写的相等
-ne 不等于
许多运算符都有一个相关的运算符来检查相反的结果。 -ne
验证这些值是否彼此相等。
if ( 5 -ne $value )
{
# do something
}
使用此选项可确保仅当值不是 5
时才执行该操作。一个很好的用例是在尝试启动服务之前检查服务是否处于运行状态。
变化:
-ne
不区分大小写不等于-ine
不区分大小写不等于-cne
区分大小写不等于
这些是 -eq
的逆变体。当我列出其他运算符的变体时,我会将这些类型分组在一起。
-gt -ge -lt -le 大于或小于
在检查一个值是否大于或小于另一个值时使用这些运算符。 -gt -ge -lt -le
代表 GreaterThan、GreaterThanOrEqual、LessThan 和 LessThanOrEqual。
if ( $value -gt 5 )
{
# do something
}
变化:
-gt
大于-igt
大于,不区分大小写-cgt
大于,区分大小写-ge
大于或等于-ige
大于等于,不区分大小写-cge
大于等于,区分大小写-lt
小于-ilt
小于,不区分大小写-clt
小于,区分大小写-le
小于或等于-ile
小于等于,不区分大小写-cle
小于等于,区分大小写
我不知道为什么您要对这些运算符使用区分大小写和不敏感的选项。
-类似通配符匹配
PowerShell 有自己的基于通配符的模式匹配语法,您可以将其与 -like
运算符一起使用。这些通配符模式相当基本。
?
匹配任何单个字符*
匹配任意数量的字符
$value = 'S-ATX-SQL01'
if ( $value -like 'S-*-SQL??')
{
# do something
}
需要指出的是,该模式与整个字符串相匹配。如果需要匹配字符串中间的某些内容,则需要将 *
放在字符串的两端。
$value = 'S-ATX-SQL02'
if ( $value -like '*SQL*')
{
# do something
}
变化:
-like
不区分大小写的通配符-ilike
不区分大小写的通配符-clike
区分大小写的通配符-notlike
不区分大小写的通配符不匹配-inotlike
不区分大小写的通配符不匹配-cnotlike
区分大小写的通配符不匹配
- 匹配正则表达式
-match
运算符允许您检查字符串是否基于正则表达式的匹配。当通配符模式对您来说不够灵活时使用此选项。
$value = 'S-ATX-SQL01'
if ( $value -match 'S-\w\w\w-SQL\d\d')
{
# do something
}
默认情况下,正则表达式模式匹配字符串中的任何位置。因此,您可以指定要匹配的子字符串,如下所示:
$value = 'S-ATX-SQL01'
if ( $value -match 'SQL')
{
# do something
}
正则表达式本身就是一门复杂的语言,值得研究。我在另一篇文章中详细讨论了 -match
以及使用正则表达式的多种方法。
变化:
-match
不区分大小写的正则表达式-imatch
不区分大小写的正则表达式-cmatch
区分大小写的正则表达式-notmatch
不区分大小写的正则表达式不匹配-inotmatch
不区分大小写的正则表达式不匹配-cnotmatch
区分大小写的正则表达式不匹配
- 属于类型
您可以使用 -is
运算符检查值的类型。
if ( $value -is [string] )
{
# do something
}
如果您正在使用类或通过管道接受各种对象,则可以使用它。您可以将服务或服务名称作为输入。然后检查您是否有服务,如果只有名称,则获取该服务。
if ( $Service -isnot [System.ServiceProcess.ServiceController] )
{
$Service = Get-Service -Name $Service
}
变化:
-is
类型-isnot
不是类型
收集运营商
当您将前面的运算符与单个值一起使用时,结果为 $true
或 $false
。使用集合时,处理方式略有不同。集合中的每个项目都会被求值,并且运算符会返回每个求值为 $true
的值。
PS> 1,2,3,4 -eq 3
3
这在 if
语句中仍然可以正常工作。所以你的操作符返回一个值,那么整个语句就是$true
。
$array = 1..6
if ( $array -gt 3 )
{
# do something
}
这里的细节中隐藏着一个小陷阱,我需要指出。当以这种方式使用 -ne
运算符时,很容易错误地向后查看逻辑。如果集合中的任何项目与您的值不匹配,则对集合使用 -ne
会返回 $true
。
PS> 1,2,3 -ne 4
1
2
3
这可能看起来是一个聪明的技巧,但我们有运算符 -contains
和 -in
可以更有效地处理这个问题。 -notcontains
可以满足您的期望。
-contains
-contains
运算符检查集合中的值。一旦找到匹配,它就会返回$true
。
$array = 1..6
if ( $array -contains 3 )
{
# do something
}
这是查看集合是否包含您的价值的首选方法。使用 Where-Object
(或 -eq
)每次都会遍历整个列表,并且速度明显慢一些。
变化:
-contains
不区分大小写的匹配-icontains
不区分大小写的匹配-ccontains
区分大小写的匹配-notcontains
不区分大小写不匹配-inotcontains
不区分大小写不匹配-cnotcontains
区分大小写不匹配
-in
-in
运算符与 -contains
运算符类似,只是集合位于右侧。
$array = 1..6
if ( 3 -in $array )
{
# do something
}
变化:
-in
不区分大小写的匹配-iin
不区分大小写的匹配-cin
区分大小写的匹配-notin
不区分大小写不匹配-inotin
不区分大小写,不匹配-cnotin
区分大小写不匹配
逻辑运算符
逻辑运算符用于反转或组合其他表达式。
-not
-not
运算符将表达式从 $false
翻转为 $true
或从 $true
翻转为 $假
。下面是一个示例,我们希望在 Test-Path
为 $false
时执行操作。
if ( -not ( Test-Path -Path $path ) )
我们讨论的大多数运算符都有一个变体,您不需要使用 -not
运算符。但有时它还是有用的。
!操作员
您可以使用 !
作为 -not
的别名。
if ( -not $value ){}
if ( !$value ){}
您可能会发现来自其他语言(例如 C#)的人更多地使用 !
。我更喜欢把它打印出来,因为我发现快速查看脚本时很难看清。
-and
您可以使用 -and
运算符组合表达式。当您这样做时,两边都需要为 $true
才能使整个表达式为 $true
。
if ( ($age -gt 13) -and ($age -lt 55) )
在此示例中,左侧的 $age
必须为 13 岁或以上,右侧的$age
必须小于 55 岁。我添加了额外的括号以使其在该示例中更清晰,但只要表达式简单,它们就是可选的。这是没有它们的相同示例。
if ( $age -gt 13 -and $age -lt 55 )
评估从左到右进行。如果第一项的计算结果为 $false
,则它会提前退出并且不会执行正确的比较。当您需要在使用某个值之前确保该值存在时,这非常方便。例如,如果您为其提供 $null
路径,则 Test-Path
会引发错误。
if ( $null -ne $path -and (Test-Path -Path $path) )
-or
-or
允许您指定两个表达式,如果其中一个为 $true
,则返回 $true
。
if ( $age -le 13 -or $age -ge 55 )
就像 -and
运算符一样,计算从左到右进行。但如果第一部分为 $true
,则整个语句为 $true
并且不会处理表达式的其余部分。
另请注意这些运算符的语法如何工作。您需要两个单独的表达式。我见过用户尝试执行类似 $value -eq 5 -or 6
的操作,但没有意识到自己的错误。
-xor 异或
这个有点不寻常。 -xor
只允许一个表达式计算结果为 $true
。因此,如果两项均为 $false
或两项均为 $true
,则整个表达式为 $false
。另一种看待这个问题的方法是,只有当表达式的结果不同时,表达式才为 $true
。
很少有人会使用这个逻辑运算符,我也想不出一个很好的例子来说明为什么我会使用它。
按位运算符
位运算符对值中的位执行计算并生成新值作为结果。按位运算符的教学超出了本文的范围,但这里是它们的列表。
-band
二进制 AND-bor
二进制或-bxor
二进制异或-bnot
二进制 NOT-shl
左移-shr
右移
PowerShell 表达式
我们可以在条件语句中使用普通的 PowerShell。
if ( Test-Path -Path $Path )
Test-Path
执行时返回 $true
或 $false
。这也适用于返回其他值的命令。
if ( Get-Process Notepad* )
如果有返回的进程,则计算结果为 $true
;如果没有,则计算结果为 $false
。使用管道表达式或其他 PowerShell 语句是完全有效的,如下所示:
if ( Get-Process | Where Name -eq Notepad )
这些表达式可以使用 -and
和 -or
运算符相互组合,但您可能必须使用括号将它们分解为子表达式。
if ( (Get-Process) -and (Get-Service) )
检查 $null
如果 if
语句中没有结果或 $null
值,则计算结果为 $false
。专门检查 $null
时,最佳做法是将 $null
放在左侧。
if ( $null -eq $value )
在 PowerShell 中处理 $null
值时存在很多细微差别。如果您有兴趣深入了解,我有一篇文章介绍了您想了解的有关 $null 的所有信息。
条件内的变量赋值
我差点忘了添加这个,直到 Prasoon Karunan V 提醒我。
if ($process=Get-Process notepad -ErrorAction ignore) {$process} else {$false}
通常,当您为变量分配值时,该值不会传递到管道或控制台。当您在子表达式中进行变量赋值时,它确实会传递到管道。
PS> $first = 1
PS> ($second = 2)
2
看看 $first
赋值没有输出而 $second
赋值有输出吗?当在 if
语句中完成赋值时,它的执行方式与上面的 $second
赋值类似。这是一个关于如何使用它的干净示例:
if ( $process = Get-Process Notepad* )
{
$process | Stop-Process
}
如果为 $process
分配了一个值,则该语句为 $true
并且 $process
将停止。
确保不要将其与 -eq
混淆,因为这不是相等检查。这是一个比较晦涩的功能,大多数人没有意识到它是这样工作的。
来自脚本块的变量赋值
您还可以使用 if
语句脚本块为变量赋值。
$discount = if ( $age -ge 55 )
{
Get-SeniorDiscount
}
elseif ( $age -le 13 )
{
Get-ChildDiscount
}
else
{
0.00
}
每个脚本块都将命令的结果或值写入作为输出。我们可以将 if
语句的结果分配给 $discount
变量。该示例可以轻松地将这些值直接分配给每个脚本块中的 $discount
变量。我不能说我经常将其与 if
语句一起使用,但我确实有一个最近使用它的示例。
备用执行路径
if
语句不仅允许您在语句为 $true
时指定操作,还可以在语句为 $false
时指定操作。这就是 else
语句发挥作用的地方。
别的
使用时,else
语句始终是 if
语句的最后一部分。
if ( Test-Path -Path $Path -PathType Leaf )
{
Move-Item -Path $Path -Destination $archivePath
}
else
{
Write-Warning "$path doesn't exist or isn't a file."
}
在此示例中,我们检查 $path
以确保它是一个文件。如果我们找到该文件,我们就会移动它。如果没有,我们会写一个警告。这种类型的分支逻辑很常见。
嵌套 if
if
和 else
语句采用脚本块,因此我们可以在其中放置任何 PowerShell 命令,包括另一个 if
语句。这允许您使用更复杂的逻辑。
if ( Test-Path -Path $Path -PathType Leaf )
{
Move-Item -Path $Path -Destination $archivePath
}
else
{
if ( Test-Path -Path $Path )
{
Write-Warning "A file was required but a directory was found instead."
}
else
{
Write-Warning "$path could not be found."
}
}
在此示例中,我们首先测试快乐路径,然后对其采取行动。如果失败,我们会进行另一次检查并向用户提供更详细的信息。
否则
我们不仅限于一次条件检查。我们可以将 if
和 else
语句链接在一起,而不是使用 elseif
语句嵌套它们。
if ( Test-Path -Path $Path -PathType Leaf )
{
Move-Item -Path $Path -Destination $archivePath
}
elseif ( Test-Path -Path $Path )
{
Write-Warning "A file was required but a directory was found instead."
}
else
{
Write-Warning "$path could not be found."
}
执行是从上到下进行的。首先评估顶部的 if
语句。如果是 $false
,那么它将向下移动到列表中的下一个 elseif
或 else
。最后一个 else
是在其他都没有返回 $true
时执行的默认操作。
转变
说到这里,我需要提一下switch
语句。它提供了一种用于对值进行多次比较的替代语法。使用开关
,您可以指定一个表达式,然后将该结果与几个不同的值进行比较。如果这些值之一匹配,则执行匹配的代码块。看一下这个例子:
$itemType = 'Role'
switch ( $itemType )
{
'Component'
{
'is a component'
}
'Role'
{
'is a role'
}
'Location'
{
'is a location'
}
}
可以匹配 $itemType
的三个可能值。在本例中,它与Role
匹配。我使用一个简单的示例只是为了让您了解 switch
运算符。我在另一篇文章中详细讨论了您想了解的有关 switch 语句的所有内容。
数组内联
我有一个名为 Invoke-SnowSql 的函数,它启动带有多个命令行参数的可执行文件。这是该函数的一个片段,我在其中构建了参数数组。
$snowSqlParam = @(
'--accountname', $Endpoint
'--username', $Credential.UserName
'--option', 'exit_on_error=true'
'--option', 'output_format=csv'
'--option', 'friendly=false'
'--option', 'timing=false'
if ($Debug)
{
'--option', 'log_level=DEBUG'
}
if ($Path)
{
'--filename', $Path
}
else
{
'--query', $singleLineQuery
}
)
$Debug
和 $Path
变量是最终用户提供的函数参数。我在数组的初始化过程中内联评估它们。如果 $Debug
为 true,则这些值将落入 $snowSqlParam
的正确位置。对于 $Path
变量也是如此。
简化复杂操作
您不可避免地会遇到需要检查太多比较的情况,并且您的 If
语句会滚动到屏幕右侧之外。
$user = Get-ADUser -Identity $UserName
if ( $null -ne $user -and $user.Department -eq 'Finance' -and $user.Title -match 'Senior' -and $user.HomeDrive -notlike '\server\*' )
{
# Do Something
}
它们可能难以阅读,并且使您更容易犯错误。对此我们可以做一些事情。
线路延续
PowerShell 中有一些运算符可让您将命令包装到下一行。如果您想将表达式分成多行,则逻辑运算符 -and
和 -or
是很好的运算符。
if ($null -ne $user -and
$user.Department -eq 'Finance' -and
$user.Title -match 'Senior' -and
$user.HomeDrive -notlike '\server\*'
)
{
# Do Something
}
那里还有很多事情要做,但是将每个部分放在自己的线上会产生很大的不同。当我得到两个以上的比较或者我必须滚动到右侧才能阅读任何逻辑时,我通常会使用它。
预计算结果
我们可以将该语句从 if
语句中取出,只检查结果。
$needsSecureHomeDrive = $null -ne $user -and
$user.Department -eq 'Finance' -and
$user.Title -match 'Senior' -and
$user.HomeDrive -notlike '\server\*'
if ( $needsSecureHomeDrive )
{
# Do Something
}
这感觉比前面的例子干净多了。您还有机会使用变量名称来解释您真正要检查的内容。这也是自记录代码的示例,可以节省不必要的注释。
多个 if 语句
我们可以将其分解为多个语句并一次检查一个。在这种情况下,我们使用标志或跟踪变量来组合结果。
$skipUser = $false
if( $null -eq $user )
{
$skipUser = $true
}
if( $user.Department -ne 'Finance' )
{
Write-Verbose "isn't in Finance department"
$skipUser = $true
}
if( $user.Title -match 'Senior' )
{
Write-Verbose "Doesn't have Senior title"
$skipUser = $true
}
if( $user.HomeDrive -like '\server\*' )
{
Write-Verbose "Home drive already configured"
$skipUser = $true
}
if ( -not $skipUser )
{
# do something
}
我确实必须反转逻辑才能使标志逻辑正常工作。每个评估都是一个单独的 if
语句。这样做的好处是,当你调试时,你可以准确地知道逻辑在做什么。我能够同时添加更详细的内容。
明显的缺点是需要编写更多代码。该代码看起来更复杂,因为它需要一行逻辑并将其分解为 25 行或更多行。
使用函数
我们还可以将所有验证逻辑移至一个函数中。看看这一眼看上去多干净。
if ( Test-SecureDriveConfiguration -ADUser $user )
{
# do something
}
您仍然需要创建函数来进行验证,但这使得此代码更易于使用。它使这段代码更容易测试。在测试中,您可以模拟对 Test-ADDriveConfiguration
的调用,并且只需对此函数进行两次测试。一种返回 $true
,另一种返回 $false
。测试另一个函数更简单,因为它很小。
该函数的主体仍然可以是我们开始使用的单行代码或我们在上一节中使用的分解逻辑。这对于这两种情况都很有效,并且允许您稍后轻松更改该实现。
错误处理
if
语句的一个重要用途是在遇到错误之前检查错误条件。一个很好的例子是在尝试创建文件夹之前检查该文件夹是否已存在。
if ( -not (Test-Path -Path $folder) )
{
New-Item -Type Directory -Path $folder
}
我想说的是,如果你期望异常发生,那么它就不是真正的异常。因此,请检查您的价值观并尽可能验证您的条件。
如果您想更深入地了解实际的异常处理,我有一篇文章介绍了您想了解的有关异常的所有内容。
最后的话
if
语句是一个非常简单的语句,但却是 PowerShell 的基本部分。您会发现自己在编写的几乎每个脚本中都会多次使用它。我希望你比以前有更好的理解。
猜你还喜欢
- 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