在Powershell中工作时,如何在列表项之间暂停



我已经做了一段时间了,在任何地方都找不到这种利用率。我使用的是powershell数组和foreach语句:@('program 1','program 2','program 3').foreach{winget show $_ -args}

然后我想在每一个之间暂停,所以我添加了;sleep 1
这不起作用。它会暂停3秒(例如基于此(,然后列出项目。我在这里错过了什么?

事实上,它似乎不尊重订单,我不知道技术原因。您可以使用普通的ForEach-Object

'program 1','program 2','program 3' | ForEach-Object {
winget show $_
sleep 1
}

或者强制输出到控制台而不是"输出";缓冲的";

('program 1','program 2','program 3').ForEach{
winget show $_ | Out-Host
sleep 1
}

Doug Maurer的帮助回答提供了有效的解决方案

关于您看到的行为的解释

内部.ForEach()方法首先收集传递给它的脚本块({ ... }(的连续每个输入对象调用产生的所有成功输出,并且只有在处理完所有输入对象后才以[System.Collections.ObjectModel.Collection[psobject]]实例的形式将收集的结果输出到管道,即成功输出流。

换句话说:

  • 与其对应的cmdletForEach-Objectcmdlet不同,.ForEach()方法不会将其脚本块中产生的输出立即发送到管道。

  • 与任何方法一样,只有当方法返回时,成功输出才会发送到管道

    • 请注意,非PowerShell。NET方法只会产生成功输出(这是它们的返回值(,并且只会通过异常通信失败,这些异常将成为终止PowerShell错误的statement

相比之下,以下do.ForEach()调用的脚本块内产生即时效果:

  • 暂时暂停执行,例如通过Start-Sleep

  • 强制即时显示(主机(输出,例如通过Out-HostWrite-Host

    • 请注意,使用Out-Host托管输出会完全阻止捕获输出,而PowerShell v5+中的Write-Host输出只能通过信息输出流(编号6(捕获
  • 写入成功输出流之外的输出流,例如通过Write-ErrorWrite-WarningWrite-Verbose -Verbose

或者,您可以使用foreach语句,该语句与ForEach-Objectcmdlet一样,也会立即向成功输出流发出输出:

# Stand-alone foreach statement: emits each number right away.
foreach ($i in 1..3) { $i; pause }
# In a pipeline, you must call it via & { ... } or . { ... }
# to get streaming behavior.
# $(...), the subexpression operator would NOT stream, 
# i.e. it would act like the .ForEach() method.
& { foreach ($i in 1..3) { $i; pause } } | Write-Output

最新更新