我已经做了一段时间了,在任何地方都找不到这种利用率。我使用的是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]]
实例的形式将收集的结果输出到管道,即成功输出流。
换句话说:
-
与其对应的cmdlet
ForEach-Object
cmdlet不同,.ForEach()
方法不会将其脚本块中产生的输出立即发送到管道。 -
与任何方法一样,只有当方法返回时,成功输出才会发送到管道。
- 请注意,非PowerShell。NET方法只会产生成功输出(这是它们的返回值(,并且只会通过异常通信失败,这些异常将成为终止PowerShell错误的statement
相比之下,以下do在.ForEach()
调用的脚本块内产生即时效果:
-
暂时暂停执行,例如通过
Start-Sleep
-
强制即时显示(主机(输出,例如通过
Out-Host
或Write-Host
。- 请注意,使用
Out-Host
托管输出会完全阻止捕获输出,而PowerShell v5+中的Write-Host
输出只能通过信息输出流(编号6
(捕获
- 请注意,使用
-
写入成功输出流之外的输出流,例如通过
Write-Error
、Write-Warning
或Write-Verbose -Verbose
。
或者,您可以使用foreach
语句,该语句与ForEach-Object
cmdlet一样,也会立即向成功输出流发出输出:
# 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