PowerShell中的ForEach和ForEach-Object之间的区别

时间:2015-03-19 15:18:48

标签: powershell

ForEachForEach-Object之间有什么区别吗?

我有一个像这样的小代码,工作正常

$txt = Get-Content 'C:\temp\000.txt'
$result = foreach ($line in $txt) {$line.replace(".ini","")}
$result | out-file 'c:\temp\001.txt'

但如果我使用' ForEach-Object',我就会出错......

$txt = Get-Content 'C:\temp\000.txt'
$result = foreach-object ($line in $txt) {$line.replace(".ini","")}
$result | out-file 'c:\temp\001.txt'

为什么?以及如何使用ForEach-Object

输出循环结果

4 个答案:

答案 0 :(得分:17)

foreachForEach-Object的别名,但它似乎也是一个关键字(令人困惑)。

您使用的foreach ($<item> in $<collection\>){<statement list>}语法为help about_foreach

foreachForEach-Object别名为help ForEach-Object

关键字foreach$<item>$<collection>中的每个()进行操作。

别名foreach / function ForEach-Object对作为输入接收的集合的每个项目进行操作。

答案 1 :(得分:16)

他们针对不同目的使用不同的命令。在管道中使用ForEach-Object cmdlet ,并使用$ PSItem或$ _来引用当前对象,以便像这样运行{scriptblock}:

1..5 | ForEach-Object {$_}

>1
>2
>3
>4
>5

现在,您还可以在一行的开头使用非常类似的关键字,ForEach。在这种情况下,您可以运行{scriptblock}来定义变量名称,如下所示:

ForEach ($number in 1..5){$number}
>1
>2
>3
>4
>5

这里的核心区别在于您使用命令的位置,一个用于管道中,另一个用于启动自己的管道。在生产样式脚本中,我建议使用ForEach关键字而不是cmdlet。

答案 2 :(得分:5)

以上两个答案都是正确的,但是https://blogs.technet.microsoft.com/heyscriptingguy/2014/07/08/getting-to-know-foreach-and-foreach-object/都有很好的总结:

  

在将输入管道传递到ForEach时,它是以下项的别名   ForEach对象。但是,当您将ForEach放置在   这是Windows PowerShell语句。

更多详细信息:

  

ForEach语句将所有前面的项目加载到   一次处理它们之前收集。每个对象   期望通过管道流式传输项目,从而降低了   内存需求,但同时会影响性能。

然后,他包括一些性能指标并得出结论:

  

那么您使用哪一个呢?好吧,答案是:“取决于情况。”您可以   使用ForEach遍历项目集合   语句或ForEach-Object cmdlet。如果您有,ForEach就是完美的   足够的内存,想要最好的性能,并且不在乎   通过管道将输出传递给另一个命令。每个对象   (具有别名%和ForEach)(从管道中获取输入)。   尽管处理所有内容的速度较慢,但​​可以为您带来好处   开始,处理和结束块。此外,它还允许您   通过管道将对象流式传输到另一个命令。到底,   使用最适合您的需求和能力的方法   您的系统。

答案 3 :(得分:0)

除了前面提到的技术差异之外,为完整性起见,这里还有一些实际差异(see also):

1。)在管道中,您不知道已处理项目的总数。在这种情况下,您将选择先获取完整列表,然后再进行foreach循环。

示例:

$files = gci "c:\fakepath"
$i = 0
foreach ($file in $files) {
    $i++
    Write-Host "$i / $($files.Count) processed"
}

2。)对于现有列表,foreach循环比管道版本要快,因为不必每次都调用脚本块。 (但是根据您所做的工作和项目的数量,差异可能微不足道。)

示例:

$items = 0..100000
Measure-Command { $items | ForEach-Object { $_ } }
# ~500ms on my machine
Measure-Command { foreach ($i in $items) { $i } }
# ~70ms on my machine