【问题标题】:Powershell pipeline foreach-objectPowershell 管道 foreach-object
【发布时间】:2017-10-06 12:44:59
【问题描述】:

为什么我不能将结果从一个 foreach-object 操作传递到另一个 foreach-object 操作?我无法运行最后一个 ForEach-Object 循环。它什么也不输出。

$mailboxstatistics |
Select-Object -First 20 |
Where { $_.FolderPath.Contains("/Inkorg") -eq $True } |
ForEach-Object -Begin{
        Write-Host "Begin"
    } -Process{
        #Write-Host "Process"
        Write-Host $($_.FolderPath)
    } -End{
        Write-Host "End"
    } |
ForEach-Object{
    Write-Host "test"
}

【问题讨论】:

  • Write-Host 不是 Write-Output。您通常都不使用(明确地),只需返回管道本身中的值(与Write-Output 调用具有相同的效果)。
  • 不要害怕破坏你的陈述。将变量设置为 First 20 where 的内容,然后将此变量通过管道传输到第一个 foreach,然后将其通过管道传输到下一个 foreach。不过,在您的情况下,我不明白您为什么不在第一个 foreach 中执行所有需要的操作。
  • 似乎我在对象上使用了 Write-Host,($_.FolderPath) 是阻止循环传递对象的罪魁祸首。谢谢,不知道。如果我想在传递管道时打印一个对象属性值(不阻塞它),是否有一个像 debug.writeline() 一样的正确命令?
  • Write-Host 没有阻塞任何东西——它根本不是管道的一部分。你的第二个 ForEach 没有做任何事情,因为没有对象传递给它。如果要打印值在管道中传递它,请使用Write-Host除了产生管道输出(但最终结果无论如何都会在控制台结束,因此这可能会导致输出混乱)。
  • 除了管道之外,还有Tee-Object可以复制到变量或文件中(虽然它不能直接复制到主机输出)。

标签: powershell


【解决方案1】:

编辑我的原始答案:您问的是“为什么管道不允许您从一个 ForEach 管道到另一个 ForEach”,而不是实际的解决方案。这需要对管道的功能有一个基本的定义。来自

  • PowerShell:自动执行管理任务,作者:Michael Shepard; Chendrayan Venkatesan;谢里夫·塔拉特;布伦顿 J.W.布拉瓦特 “PowerShell 中的管道是一种从一个命令到另一个命令获取数据的机制。简单地说,第一个命令输出的数据被视为管道中下一个命令的输入。”

PowerShell 中的管道传递 .NET 框架对象,而其他类型的 shell 则可能传递文本。那么,根据上面的定义,您期望 For-EachObject 输出什么作为下一个序列的管道输入?当您在执行 Where-Object 或 Select-Object 时,您正在优化集合。您已经声明将对象发送到 Write-Host。 ForEach 完成后,管道中不会有任何输出。

我不确定流水线菊花链的优势。我可能错了,我通常用变量打破序列。 ForEach 将消耗和操作通过管道输入的集合的每一个项目,然后生产或输出到底是什么,到管道链中的下一个?我了解 ForEach 可以接受管道输入作为对象集合,例如数组。所以我看到了它只使用迭代项目数量的优势,而不是经典的

for($i = 0; $i-lt $collectionOfOjbects.Length; $i++)
{
     Verb-Noun $collectionOfObjects[$i]
}

是否可以先尝试选择/排序精炼,然后将其传递给 ForEach 迭代?

$myFirst20MailboxStatsInkorg = $mailboxstatistics | Select-Object -First 20 | Where { $_.FolderPath.Contains("/Inkorg") -eq $True } 
#first round of iteration:
$myFirst20MailboxStatsInkorg | ForEach-Object -Begin{
        Write-Host "Begin"
    } -Process{
        #Write-Host "Process"
        Write-Host $($_.FolderPath)
    } -End{
        Write-Host "End"
    }
#second round of iteration
$myFirst20MailboxStatsInkorg | ForEach-Object{
    Write-Host "test"
}

【讨论】:

  • 当然可以,但这个问题通常更多地是关于为什么第一个 foreach-object 循环没有将对象传递到管道中。为什么 Write-Host 将整个对象转移到主机,而不仅仅是对象属性的值。
猜你喜欢
  • 2011-12-06
  • 2014-02-13
  • 2013-01-08
  • 2011-04-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多