【问题标题】:Difference between ForEach and ForEach-Object in powershellPowershell中ForEach和ForEach-Object的区别
【发布时间】:2015-03-19 15:18:48
【问题描述】:

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输出循环结果

【问题讨论】:

标签: powershell


【解决方案1】:

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

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

foreach 作为ForEach-Object 的别名是help ForEach-Object

关键字foreach 作用于$<collection> 中的每个$<item>,如() 位中所给。

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

【讨论】:

  • 好吧,如果我将代码更改为ForEach-Object,我会收到错误Unexpected token 'in' in expression or statement. Missing closing ')' in expression. Unexpected token ')' in expression or statement. .......
  • 对。因为ForEach-Object 不使用该语法。查看我列出的帮助文档。
  • 对于初学者级别的问题,这是一个相当高级的答案。请参阅下面@FoxDeploy 的答案以获取示例。
【解决方案2】:

它们是用于不同目的的不同命令。 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。

【讨论】:

  • 关键字:管道中使用的 ForEach-Object。不错。
  • ForEach 也可以通过管道传送到,因为它也是ForEach-Object 的别名。 (但反之则不然——ForEach-Object 不是关键字,不能用于循环。)
【解决方案3】:

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

当您将输入输入到 ForEach 时,它是 ForEach-对象。但是当你把 ForEach 放在 行,它是一个 Windows PowerShell 语句。

还有更多细节:

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

然后他包括了一些性能测量并得出结论:

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

【讨论】:

  • 也许我遗漏了什么,但如果ForEachForEach-Object 的别名,那么如何在不调用ForEach-Object 的情况下使用ForEach 关键字?
  • 我想通了,所以我想我会在这里为其他困惑的人发帖。 ForEach-Object 的语法是 ForEach-Object / ForEach / % { },而 foreach 关键字由语法 foreach ($item in $items) {} 调用
【解决方案4】:

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

1.) 在管道中,您不知道已处理项目的总 count。在这种情况下,您会选择先获取完整列表,然后执行 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

【讨论】:

    猜你喜欢
    • 2020-05-19
    • 2019-10-19
    • 2014-02-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-13
    • 2011-12-06
    相关资源
    最近更新 更多