Powershell 如何以流的形式逐行处理命令的输出

Powershell 如何以流的形式逐行处理命令的输出,powershell,Powershell,写入SomeCommand |{…}将SomeCommand的整个输出通过管道传输到大括号中的代码。有没有一种方法可以一次“管道”一行,让大括号中的代码逐行处理,而不必等待整个输出存储在内存中 更新 [摘自评论] SomeCommand是一个可执行文件(不是powershell cmdlet),在运行时会产生一些输出。它生成的行之间需要一些时间,我不想等到所有行都生成后再对每行执行一些操作。在powershell中,对象是沿着对象管道逐项传递的 管道的一个相关有用特性是,因为它们分别对每个项目进

写入
SomeCommand |{…}
SomeCommand
的整个输出通过管道传输到大括号中的代码。有没有一种方法可以一次“管道”一行,让大括号中的代码逐行处理,而不必等待整个输出存储在内存中

更新

[摘自评论]


SomeCommand
是一个可执行文件(不是powershell cmdlet),在运行时会产生一些输出。它生成的行之间需要一些时间,我不想等到所有行都生成后再对每行执行一些操作。在powershell中,对象是沿着对象管道逐项传递的

管道的一个相关有用特性是,因为它们分别对每个项目进行操作,所以不必根据管道中是否有零个、一个或多个项目来修改它们。此外,管道中的每个命令(称为管道元素)通常会逐项将其输出传递给管道中的下一个命令。这通常会减少复杂命令的资源需求,并允许您立即开始获取输出

不过也有一些例外。有些命令(如
排序对象
)需要所有输入对象才能将结果发送到对象管道中的下一步

在您的示例中,您可以使用ForEach Object cmdlet(别名为
%
),并使用其特殊的
$\uuuu
变量,该变量表示正在处理的当前项:

Get-ChildItem $pshome | ForEach-Object -Process {if (!$_.PSIsContainer) {$_.Name; $_.Length / 1024; "" }}
编辑2
由于您正在调用可执行文件,powershell将在接收stdout时将其拆分为多行,并将每个字符串沿对象管道发送。请通过@use查看答案。

为了使脚本块能够访问管道,您需要在其中包含进程块: 比较两者:

1, 2, 3 | & {
    process {
        $_
        Start-Sleep -Seconds 1
    }
}

1, 2, 3 | & {
    $input
    Start-Sleep -Seconds 1
}
显然,
Foreach对象(在前面的回答中提到过)通常比在这种情况下使用脚本块更好,但是由于您要求使用脚本块,所以脚本块也是您应该得到的…

管道输出(旧样式)通过PowerShell的
foreach
cmdlet执行的文本流:

ping.exe www.somesite.com |%{$}


说明:
%
是Foreach对象的别名。它在换行符处剪切一个文本流,并一行接一行地发出。实际上,大多数将字符串作为管道输入的cmdlet只在命令行上工作(实际上是PowerShell切断了文本流,而不是cmdlet)。

什么是SomeCommand?从您的问题来看,这听起来像是一个powershell命令,返回一个多行字符串(如调用可执行文件)。这取决于
SomeCommand
是什么。SomeCommand是一个可执行文件(不是powershell cmdlet),在运行时会产生一些输出。它生成的两行之间需要一段时间,我不想等到所有行都生成后再对每行执行某些操作。无论您是使用PS命令,还是仅使用PowerShell cmdlet。如果它输出一些东西,您可以一个接一个地处理它们,而不需要您做任何额外的工作。如果失败了,我会责怪命令作者。例如,尝试:
ping-tlocalhost |%{$\u-replace'time','after'}
。Ping只是一个可执行文件,但在管道中工作得很好:)谢谢你的回答。奇怪的是,为了实现通常使用Bash(或其他unixshell)完成的任务,我需要在powershell中执行一些高级技巧。我会继续寻找更简单的东西,如果我找到了,我会发帖回复。否则,这就是我要寻找的答案。@AlexShtof我编辑了我的答案,因为您只需要使用OutputDataReceived事件来完全手动处理标准输出。例如,如果stdout不是行分隔的,那么PowerShell将等待接收整个字符串,然后再将其发送到对象管道。在这种情况下,您仍然可以使用另一个命令,如带正则表达式的Select String,让PowerShell在输入时检查标准输出是否匹配,并尽快将每个标准输出发送到管道中。我以前看过您的评论…:)不,这不会改变我的答案。它是exec not cmdlet这一唯一事实并不意味着
$\uuu
将不包含命令输出的最后一行(一次处理一行)。