是否可以在不分配给变量的情况下通过管道传递 while 循环的结果 [英] Is it possible to pipe the result of a while loop without assigning to a variable
问题描述
以下代码无效
$result = (而 ($true) {<#生成psobject的长列表#>}) |Tee-Object -FilePath 'fname.csv' |组-对象-属性 xxx |选择名称,计数
<块引用>
术语while"未被识别为 cmdlet、函数、脚本文件或可运行程序的名称.检查名称的拼写,如果包含路径,请验证路径是否正确,然后重试.
虽然:
您可以使用表达式作为管道的第一段(例如,
1..2 | Tee-Object - 变量结果
),你不能使用复合语句,例如
if
、while
>、foreach
和do
很遗憾.
也就是说,这样的复合语句不是真正的表达式,尽管在赋值的上下文中它们可以起到这样的作用.也就是说,您可以执行 $result = while ($true) ...
- 无需在 (...)
中包含 while
-但是你不能直接通过管道发送while
循环.
参见 这个 GitHub 问题,其中讨论了这个有问题的半表达式状态";复合语句,并询问是否可以使它们成为完整的表达式;事实证明,PowerShell 语法的基础阻止了这种情况.
解决方法:
如果你想让你的循环复合语句流,即把它的对象一个一个输出到管道,如它们变得可用 - 即,如果您想要标准的流式管道行为:
- 用
& 包裹你的复合语句{ ... }
(或. { ... }
,如果您想直接在当前范围内运行而不是在子范围内运行). - 例如,
&{ foreach ($i in 1..2) { $i } } |Tee-Object - 变量结果
- 用
如果您想收集循环复合语句的所有输出预先,在通过管道发送它们之前:
- 将复合语句包装在
$(...)
中,子表达式运算符. - 例如,
$(foreach ($i in 1..2) { $i }) |Tee-Object - 变量结果
- 注意:
- 同时使用
$(...)
而不是&{ ... }
可以加速您的管道,它只是略微加速,并且它可能以内存消耗为代价,因为所有输出总是em> 首先收集到内存中. - 这同样适用于
@(...)
,array-subexpression operator 和(...)
,分组运算符,但请注意(...)
仅适用于单个 表达式 或 命令.这个答案对比了(...)
、$(...)
和@(...)
详细说明.
- 同时使用
- 将复合语句包装在
适用于您的案例:
$result = &{而 ($true) {<#生成psobject的长列表#>}} |Tee-Object -FilePath 'fname.csv' |...
The following code doesn't work
$result = (
while ($true) {
<# Generating long list of psobject #>
}) | Tee-Object -FilePath 'fname.csv' | Group-Object -Property xxx | Select Name,Count
The term 'while' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
While:
you can use expressions as the first segment of a pipeline (e.g.,
1..2 | Tee-Object -Variable result
),you cannot use compound statements such as
if
,while
,foreach
, anddo
as-is, unfortunately.
That is, such compound statements aren't true expressions, even though in the context of assignments they can act a such. That is, you could do $result = while ($true) ...
- without enclosing the while
in (...)
- yet you cannot send the while
loop directly through a pipeline.
See this GitHub issue, which discusses this problematic "half-expression status" of compound statements, and asks if it's feasible to make them full expressions; as it turns out, the fundamentals of PowerShell's grammar prevent that.
Workarounds:
If you want your looping compound statement to stream, i.e. to output its objects one by one to the pipeline, as they become available - i.e. if you want the standard, streaming pipeline behavior:
- Wrap your compound statement in
& { ... }
(or. { ... }
, if you want to run directly in the current rather than in a child scope). - E.g.,
& { foreach ($i in 1..2) { $i } } | Tee-Object -Variable result
- Wrap your compound statement in
If you want to collect all outputs from your looping compound statement up front, before sending them through the pipeline:
- Wrap your compound statement in
$(...)
, the subexpression operator. - E.g.,
$(foreach ($i in 1..2) { $i }) | Tee-Object -Variable result
- Note:
- While using
$(...)
over& { ... }
can speed up your pipeline, it does so only slightly, and it potentially comes at the expense of memory consumption, given that all outputs are invariably collected in memory first. - The same applies to
@(...)
, the array-subexpression operator and(...)
, the grouping operator, but note that(...)
only works with a single expression or command. This answer contrasts(...)
,$(...)
and@(...)
in detail.
- While using
- Wrap your compound statement in
Applied to your case:
$result = & {
while ($true) {
<# Generating long list of psobject #>
}
} | Tee-Object -FilePath 'fname.csv' | ...
这篇关于是否可以在不分配给变量的情况下通过管道传递 while 循环的结果的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!