[PowerShell入门]选择结构和循环结构

PowerShell入门

学习完PowerShell中的关系运算和逻辑运算,就可以开始学习PowerShell的控制结构了。

尽管本篇尽量减少了对于学习过其他语言读者来说不重要的内容,但为了照顾初学者(或许真的有吧…),所以还是保留了一些有必要详细讲解的内容。关于PowerShell的选择结构和循环结构中需要注意的东西,文章都相应地做了着重标记,所以非初学者的读者们可以跳过那些基础内容,直接阅读着重内容即可。

下文中关于各种语句的基本结构,在此约定:圆括号()代表表达式应该用圆括号包含。花括号{}代表这是一个代码块。方括号[]代表这是一个可选项。竖线|代表“或”。双点..代表该结构可以重复出现。前缀加上$的代表这是一个变量。


选择结构

if

PowerShell中if语句用于根据判定给定条件的结果来控制程序接下来的动作,其基本结构为if (condition) {statement} [elseif (condition) {statement} ..] [else {statement}]

程序从if子句开始从上至下逐个判断condition的结果是否为$true,是的话就执行后面的代码块并退出结构。如果没有任何子句的condition返回$true,则执行else子句后面的代码块。

# 下面的程序会根据$p变量不同的值而打印不同的字符串
$p = "bj"
if ($p -eq "bj")
{
    "Welcome to BeiJing!"
}
elseif ($p -eq "cq")
{
    "Welcome to ChongQing!"
}
else
{
    "Welcome to China!"
}

唯一需要注意的地方是PowerShell中的elseif是一个完整的关键字,而不是else和if的组合,中间是没有空格隔开的。


switch

如果选择结构有多个分支,使用if语句写起来就非常繁琐。选择分支越多,elseif子句就越多,程序就会越来越冗长,影响可读性。而switch语句就是用于简化多分支选择结构的。

switch语句的结构比较复杂,如下:

switch [-regex|-wildcard|-exact] [-casesensitive] (item)|-file filename
{
    {condition} {statement}
    ..
    [default {statement}]
}

switch关键字后面可以加上可选的参数:

  • -regex代表接受正则表达式对字符串进行匹配。
  • -wildcard代表接受通配符对字符串进行匹配。支持?、*、[a-z]等形式的通配符。
  • -exact代表精确匹配,使用精确匹配的话switch语句就不会识别字符串中的通配符和正则表达式。
  • -casesensitive代表大小写敏感,加上该参数的时候switch默认使用-ceq而不是-ieq。

以上的参数可以使用任意长度的缩写代替,比如-casesensitive可以写为-case,也可以写为-c。

item代表传入switch语句进行判断的变量或者字面量,如果使用了-file参数,则switch读取后面提供的文件中的内容进行匹配。

condition代表需要比较的条件,它可以是一个字面量或者用花括号包含起来的条件/逻辑表达式,当它是一个字面量时switch语句会使用-eq/-like/-match操作符将它与item进行比较。当condition返回$true时执行后面的代码块,否则判断下一个条件是否符合。如果没有任何条件符合,则执行default后面的代码块。在执行完statement后,PowerShell会继续执行下面的语句,如果想在执行之后跳出结构,那么需要在statement的最后加上break语句跳出整个switch。

switch语句也支持传入一个集合,这时候的switch其实相当于foreach和if的结合。在代码块中可以用$_代表当前变量。

# 判断1到10中哪些数字是偶数,哪些是奇数
$nums = 1..10
switch ($nums)
{
    {($_ % 2) -eq 0} {"$_ 是偶数"}
    {($_ % 2) -ne 0} {"$_ 是奇数"}
}

循环结构

while

while语句用于根据特定条件运行循环,其基本结构为while (condition) {statement}

程序进入while语句后,先判断condition是否为$true,是的话则执行代码块,然后再次判断condition的值。否则退出循环。

# 下面的程序从5开始打印字符串直到$x不大于1
$x = 5
while ($x -gt 1)
{
    "$x is greater than 1"
    $x--
}

do..while..和do..until..

与while语句不同,do..while和do..until..先执行一次循环体,再判断循环条件是否成立。它们的基本结构为do {statement} while|until (condition)。它们的区别是do..while..在条件成立的时候继续循环,而do..until..在条件成立的时候退出循环。

在实际的应用中,如果想保证循环体至少执行一次,那么可以选择do..while..或者do..until..结构。

# 循环读入一个字符串并将其原样输出,直到输入的字符串为"exit"
do
{
    $n = Read-Host
    Write-Output $n
} until ($n -eq "exit")

foreach

foreach用于集合的遍历,其基本结构为foreach ($item in collection) {statement}。其中collection是要进行遍历的集合,可以是变量或者字面量,item是用于代表集合中元素的临时变量。

# 遍历city集合并打印字符串
$city = "ChongQing", "BeiJing", "XiAn"
foreach ($c in $city)
{
    "Welcome to $c"
}

PowerShell中的ForEach-Object和ForEach()方法

其实PowerShell中还有另外两种遍历集合的方法,一种是使用ForEach-Object命令,还有一种是直接使用集合对象的ForEach()方法。

上面的代码也可以用ForEach-Object改写为"ChongQing", "BeiJing", "XiAn" | ForEach-Object {"Welcome to $_"}。或者用ForEach()方法改写为("ChongQing", "BeiJing", "XiAn").ForEach({"Welcome to $_"})

这两种“foreach”跟真正的foreach语句是不一样的。foreach语句不使用管道,当我们使用foreach语句来进行集合遍历的时候,实际上集合会先被加载到内存当中,再进行遍历。而ForEach-Object使用管道,每次只处理一个对象,内存的消耗比foreach语句小。但由于不是真正的循环结构,在ForEach-Object和ForEach()方法中的continue语句和break语句都无法正常工作。

另外,ForEach-Object也可以写为foreach,但这个“foreach”跟foreach语句不同,它只是ForEach-Object的alias,它只有在管道操作符右边的时候才会起作用

> Get-Alias foreach

CommandType     Name                          Version     Source
-----------     ----                          -------     -
Alias           foreach -> ForEach-Object

for

for语句用于固定数量的循环,其基本结构为for (init; condition; increment) {statement}。其中init用于初始化循环所需要用的变量,init只会执行一次,condition用于判断是否继续执行循环,increment用于在每次循环结束后递增或递减循环用到的变量。其中,init和increment可以为空。

# 打印0到9
for ($i = 0; $i -lt 10; $i++)
{
    "$i"
}

关于使用for代替while

有些书本或者教程讲循环结构的时候总会提到:for语句可以完全代替while语句,只需要把init和increment留空,for语句的作用也就完全跟while语句一样了。这种说法虽然在语法层面上没有错,但对于新手来说却是一种误导。博主认为,for和while所表达的“语义”是完全不同的。for一般用于固定次数的循环,或者在某些语言里面充当foreach的角色,而while则用于未知次数的循环或者无限循环当中,这两者是完全不该混用的。混用for和while会使程序的可读性变差,所以在条件允许的情况下,应当尽量分清几种循环结构的语义和使用场景


continue和break

当我们在使用循环结构的时候,在特定条件下可能要跳过某次循环或者退出整个循环结构。此时可以使用continue语句和break语句。continue语句的作用是跳过当前循环进入下一次循环,break语句则跳出整个循环结构。PowerShell中的循环结构都可以使用continue语句和break语句。

# 循环遍历1到10的数组,当$i等于5的时候跳过当前循环,直接执行下一次循环
foreach ($i in 1..10)
{
    if ($i -eq 5)
    {
        continue
    }
    "$i"
}

总结

PowerShell提供了多种选择结构和循环结构用于控制程序的运行,熟练掌握这些结构是构建复杂程序的基础。对于学习过其他语言的人来说,这些内容应该都不难理解。而对于学习PowerShell的人来说,学习过其他语言的应该占多数,所以本篇博客也尽量减少了那些无关紧要的废话,对其中一些与其他语言有区别的点相应地作了标记。每次写博客,博主都尽量找了更多更详细的资料,以求能把一些没人注意到的细节讲清楚(比如这篇博客中关于switch中的-file参数,pstips的在线教程中就没提到,是在一个外文网站ss64中翻到的),希望这些细节对读者们能有所帮助。


我的其他PowerShell入门相关文章:

[PowerShell入门]变量、赋值、算术运算、类型转换、数组、注释
[PowerShell入门]关系运算和逻辑运算


参考资料:

pstips
ss64
Powershell 中的 foreach 和 foreach-object

感谢以上内容提供者!

猜你喜欢

转载自blog.csdn.net/jy692405180/article/details/72885170