当前位置:网站首页 > 更多 > 玩电脑 > 正文

[玩转系统] PowerShell For Loop、ForEach 和 Do While/Until 解释

作者:精品下载站 日期:2024-12-14 03:40:47 浏览:13 分类:玩电脑

PowerShell For Loop、ForEach 和 Do While/Until 解释


除了“If, Else”之外,编程中最基本的功能之一就是循环。它们允许您处理数据或运行函数,直到达到特定条件。在PowerShell中,我们可以使用不同类型的循环For循环、ForEach、While、Do WhileDo Until

了解何时使用什么对于编写更好的 Powershell 脚本很重要。尤其是三个while循环之间的区别有时很难理解。

在本文中,我们将了解可以在 PowerShell 中使用的不同循环函数、如何使用它们以及它们之间的区别。

Powershell For 循环

PowerShell 中的 For 循环几乎是您可以使用的最基本的循环。它会迭代脚本的一部分指定的次数,直到满足条件。

要在 PowerShell 中使用 For 循环,您需要指定计数器 $i、条件 $i -lt 5(只要 $i 小于 5 就运行)并增加计数器。

For ($i = 0; $i -lt 5; $i++) {
    Write-host $i 
}

增加计数器也可以在脚本内完成。这允许您仅在脚本中满足特定条件时增加计数器。

For ($i = 0; $i -lt 5) {
    Write-Host $i;    
    $i++
}

您还可以在 PowerShell 中使用简单的 For 循环来迭代数组。我们可以将数组长度作为条件的一部分,并迭代数组,直到处理完数组中的所有项目。

使用 foreach 循环处理数组比使用 for 循环更容易,稍后会详细介绍。

$fruit = @('apple','pear','banana','lemon','lime','mango')

# -le means less or equal to
For ($i = 0; $i -le $fruit.length; $i++) {
    Write-Host $fruit[$i];    
}

PowerShell Foreach 1..10

PowerShell 还有一个可用于循环的简写。您可以定义一个范围,例如 1..10,然后使用 ForEach 语句循环遍历该范围中的每个数字。这允许您指定要运行脚本的次数,并只需在其后面通过管道传输脚本即可。

$path = "C:\temp"

# Create a new file ForEach 1..10 number 
1..10 | % {
    $newFile = "$path\test_file_" + $_ + ".txt";
    New-Item $newFile
}

PowerShell Foreach 和 ForEach 对象循环

要处理数组或集合中的每个项目,您可以使用 PowerShell 中的 ForEach 函数。

PowerShell中有两种类型的foreach函数,分别是foreachForEach-Object。两者之间的区别在于,foreach 会在开始处理数据之前将整个集合加载到内存中,而 ForEach-Object 会一次处理一个数据。这使得 ForEach-Object 非常适合在另一个函数后面进行管道传输。

ForEach-Object 有两种可以使用的简写形式:ForEach%。使用 ForEach 的地方决定了使用两者的哪个版本。

$fruits = @('apple','pear','banana','lemon','lime','mango')

# Foreach - Loads all the fruits in the memory and process it
# Takes 21,4553 miliseconds
Foreach ($fruit in $fruits) {
    Write-Host $fruit;
}

#Shorthand for foreach
# Takes 14,3926 miliseconds
$fruits.foreach( {
    Write-Host $_;
}) 

# ForEach-Object 
# Takes 7,8812 miliseconds
$fruits | ForEach-Object {Write-Host $_}

# Shorthand for ForEach-Object
# Takes 7.3507 miliseconds
$fruits | ForEach {Write-Host $_}

# Also a Shorthand for ForEach-Object
# Takes 7,2982 miliseconds
$fruits | % {Write-Host $_}

正如您所看到的,在这个例子中 foreach 有点慢,但原因是需要一点时间才能将集合加载到内存中。

如果我们采用一个大型数据集,例如有 300.000 条记录,那么我们可以看到 foreach 比 ForEach-Object 快得多。只是内存消耗会比foreach高一点。

$items = 0..300000

# Takes 180 ms to complete
(Measure-Command { foreach ($i in $items) { $i } }).TotalMilliseconds

# Takes 1300 ms to complete
(Measure-Command { $items | ForEach-Object { $_ } }).TotalMilliseconds

# Takes 850 ms to complete
(Measure-Command { $items.ForEach({ $i })}).TotalMilliseconds

当您使用哪个函数实际上取决于您的数据集。如果您需要处理大量数据,那么 ForEach-Object 将是避免内存问题的最佳选择。小数据集可以用 ForEach 完美处理。

ForEach-Object 的另一个优点是您可以在其后面通过管道传输另一个 cmdlet,例如将其导出到 CSV。

ForEach-Object 脚本块

ForEach-Object 允许您使用脚本块,当您需要记录进程或在脚本完成时进行清理时,这非常有用。

$path = "C:\temp"
$totalSize = 0

Get-ChildItem $path | ForEach-Object -Begin {
        Write-Host "Processing folder $path"
    } -Process {
        $totalSize += ($_.length / 1kb)
    } -End {
        Write-host $totalSize "Kb"
    }

Powershell Do While 循环

PowerShell Do While 循环用于只要条件为 True 或满足就运行脚本。 PowerShell 中还有 While 循环,但没有 Do 部分。它们基本上是相同的,都是运行直到满足条件。

如果运行下面的脚本,您将看到它们在临时文件夹中都有 10 个测试文件。只要 $i 小于 10,两者都会运行。

$i = 0;
$path = "C:\temp"

# Do While loop
Do {
    # Do Something
    $newFile = "$path\dowhile_test_file_" + $i + ".txt";
    New-Item $newFile
    $i++;
}
While ($i -lt 10)

# While loop
$i = 0;
While ($i -lt 10) {
    # Do Something
    $newFile = "$path\while_test_file_" + $i + ".txt";
    New-Item $newFile
    $i++;
}

两者之间有一个很大的区别。无论您使用的条件是什么,Do While 总是至少运行一次。 while循环只有在满足条件时才会运行。

拿下面的例子来说,我们想要运行脚本,只要$i小于10。但是我们首先将计数器设置为15。正如您在运行脚本时将看到的那样,Do While 确实运行一次,而 while 根本不运行。

$i = 15;

Do {
    Write-host "Do While $i is less then 15";
    $i++;
}
While ($i -lt 10)

$i = 15;
while ($i -lt 10)
{
    Write-host "While $i is less then 15";
    $i++;
}

当您等待满足条件时,例如直到进程完成或如下例所示,直到互联网连接离线,您经常在 PowerShell 中使用 do-while 循环。

在满足 while 条件之前,PowerShell 不会继续写入主机行。因此,在此示例中,我们使用 Test-Connection 测试互联网连接。当我们有连接时它将返回 true,否则它将返回 false。

Do {
    Write-Host "Online"
    Start-Sleep 5
}
While (Test-Connection -ComputerName 8.8.8.8 -Quiet -Count 1)

Write-Host "Offline"

在 PowerShell 中创建睡眠循环

如果您想创建一个循环来检查服务是否重新联机,或者要创建的文件,那么最好的选择是在循环内使用睡眠。

如果没有睡眠部分,脚本将尽可能快地运行,可以是每秒 1000 次迭代或更多。

使用 Start-Sleep cmdlet,我们可以在下一次迭代之前启动一点休息:

Do {
    Write-Host "Online"
    Start-Sleep 5
}
While (Test-Connection -ComputerName 8.8.8.8 -Quiet -Count 1)

Write-Host "Offline"

在上面的示例中,我们等待 5 秒,然后再次测试与 8.8.8.8 的连接。您还可以在 start-sleep 命令中使用毫秒而不是秒。

Start-Sleep -Miliseconds 50

PowerShell Do Until 循环

Do Until 与 PowerShell 中的 Do While 几乎相同。唯一的区别是它们运行的条件。

  • Do While只要条件为真就会继续运行。当条件为假时,它将停止。
  • Do Until只要条件为 false 就会继续运行。当条件成立时,它将停止。
Do {
    Write-Host "Computer offline"
    Start-Sleep 5
}
Until (Test-Connection -ComputerName 'lab01-srv' -Quiet -Count 1)

Write-Host "Computer online"

何时使用 While 或 Until 实际上取决于您想要做什么。是根据你可以说,当退出条件必须为真时,然后使用Until。如果退出条件为负(假),那么您应该使用 While。

停止 Do While/Until 循环

在PowerShell中,我们可以使用Break提前停止循环。最好限制循环中中断的使用,因为它们会使代码更难阅读。如果你的代码结构很好,那么你真的不需要它。

$i=0;
Do {
    Write-Host "Computer offline"
    Start-Sleep 1
    $i++;

    if ($i -eq 2) {
        Break
    }
}
Until (Test-Connection -ComputerName 'test' -Quiet -Count 1)

在 PowerShell 循环中使用Continue

您可以在 PowerShell 中的 do-while/until 循环中使用的另一个有用方法是继续。使用Continue,您可以停止Do 主体内的脚本并继续循环的下一次迭代。

如果 Do 块内有一个大型脚本并且想要在满足特定条件时跳到下一项,这会很有用。

$servers = @('srv-lab01','srv-lab02','srv-lab03')

Foreach ($server in $servers) {
    
    if ((Test-Connection -ComputerName $server -Quiet -Count 1) -eq $false) {
        Write-warning "server $server offline"
        Continue
    }

    # Do stuff when server is online
}

PowerShell 循环示例

下面您将找到几个循环示例,它们可能有助于创建您自己的循环。

PowerShell 无限循环

您可以使用 While 循环函数在 PowerShell 中创建无限循环。只要条件为真,While 就会继续运行。因此,要创建无限循环,我们可以简单地执行以下操作:

While ($true) {
    # Do stuff forever
    Write-Host 'looping'

    # Use Break to exit the loop
    If ($condition -eq $true) {
        Break
    }
}

要退出无限循环,您可以使用Ctrl + C或根据条件使用Break

Powershell 循环文件

为了循环遍历文件,我们将使用 foreach-object 函数。文件是我们可以使用 get-childitem cmdlet 获取的对象,因此我们可以在其后面通过管道传输 foreach-object。使用 ForEach-Object 而不是 foreach 的另一个原因是我们事先不知道要处理多少个文件。

Foreach 将加载内存中的所有数据,这是我们不希望使用未知数据集的情况。

$path = "C:\temp"
$csvItems = 0

Get-ChildItem $path | ForEach-Object {
    $_.Name;

    If ($_.Extension -eq '.csv') {
        $csvItems++;
    }
}

Write-host "Total CSV Files are $csvItems";

如果您还想包含子文件夹,可以使用 -recurse 选项。例如,使用 -filter 仅获取 .csv 文件。

Get-ChildItem $path -recurse -filter *.csv

循环遍历文本文件

在 PowerShell 中,您可以逐行循环遍历文本文件。例如,如果您想自动读出日志文件,这非常有用。

下面的示例适用于小文件,但问题是 Get-Content 会将整个文件读入内存。

$lineNr = 0

foreach($line in Get-Content c:\temp\import-log.txt) {
    if($line -match 'warning'){
        # Work here
        Write-warning "Warning found on line $lineNr :"
        Write-warning $line
    }

    $lineNr++;
}

要使用 PowerShell 读取和处理较大的文件,您还可以使用 .Net 文件读取器:

foreach($line in [System.IO.File]::ReadLines("c:\temp\import-log.txt"))
{
       $line
}

总结

我希望该示例有助于创建 PowerShell For、Foreach-Object、Do While 和 Until 循环。如果您有任何疑问,请在下面发表评论。

您需要 登录账户 后才能发表评论

取消回复欢迎 发表评论:

关灯