ForEach-Object

针对输入对象集合中的每个项执行操作。

语法

ForEach-Object
            [-InputObject <PSObject>]
            [-Begin <ScriptBlock>]
            [-Process] <ScriptBlock[]>
            [-End <ScriptBlock>]
            [-RemainingScripts <ScriptBlock[]>]
            [-WhatIf]
            [-Confirm]
            [<CommonParameters>]
ForEach-Object
            [-InputObject <PSObject>]
            [-MemberName] <String>
            [-ArgumentList <Object[]>]
            [-WhatIf]
            [-Confirm]
            [<CommonParameters>]

说明

ForEach-Object cmdlet 对输入对象集合中的每个项执行操作。 输入对象可以通过管道传递给 cmdlet,也可以使用 InputObject 参数指定。

从 Windows PowerShell 3.0 开始,可通过两种不同的方法来构造ForEach-Object命令。

  • 脚本块。 你可以使用某个脚本块来指定操作。 在脚本块中,使用 $_ 变量表示当前对象。 脚本块是 Process 参数的值。 脚本块可以包含任何 PowerShell 脚本。

    例如,以下命令将获取计算机上每个进程的 ProcessName 属性值。

    Get-Process | ForEach-Object {$_.ProcessName}

    ForEach-Object支持about_functions中所述的beginprocessend块。

    注意

    脚本块在调用方的范围中运行。 因此,这些块可以访问该作用域中的变量,并且可以在 cmdlet 完成后创建在该作用域中保留的新变量。

  • 操作语句。 还可以编写一个操作语句,这更像是自然语言。 你可以使用该操作语句来指定属性值或调用方法。 Windows PowerShell 3.0 中引入了操作语句。

    例如,以下命令还将获取计算机上每个进程的 ProcessName 属性值。

    Get-Process | ForEach-Object ProcessName

示例

示例 1:在数组中除整数

此示例采用三个整数的数组,并将其中每个整数除以 1024。

30000, 56798, 12432 | ForEach-Object -Process {$_/1024}

29.296875
55.466796875
12.140625

示例 2:获取目录中所有文件的长度

此示例处理 PowerShell 安装目录中的文件和目录 $PSHOME

Get-ChildItem $PSHOME |
  ForEach-Object -Process {if (!$_.PSIsContainer) {$_.Name; $_.Length / 1024; " " }}

如果对象不是目录,则脚本块获取文件的名称,将其 Length 属性的值除以 1024,并添加空格 (“) 以将其与下一个条目分开。 该 cmdlet 使用 PSISContainer 属性来确定对象是否为目录。

示例 3:对最新的系统事件进行操作

本示例将 1000 个最新事件从系统事件日志写入文本文件。 当前时间显示在处理事件之前和之后。

$Events = Get-EventLog -LogName System -Newest 1000
$events | ForEach-Object -Begin {Get-Date} -Process {Out-File -FilePath Events.txt -Append -InputObject $_.Message} -End {Get-Date}

Get-EventLog 从系统事件日志中获取 1000 个最新事件,并将其存储在变量中 $Events$Events 然后通过管道传递给 ForEach-Object cmdlet。 Begin 参数将显示当前日期和时间。 接下来, Process 参数使用 Out-File cmdlet 创建一个名为events.txt的文本文件,并将每个事件的消息属性存储在该文件中。 最后,在完成所有处理之后,使用 End 参数显示日期和时间。

示例 4:更改注册表项的值

本示例将项下HKCU:\Network的所有子项中的 RemotePath 注册表项的值更改为大写文本。

Get-ItemProperty -Path HKCU:\Network\* |
  ForEach-Object {Set-ItemProperty -Path $_.PSPath -Name RemotePath -Value $_.RemotePath.ToUpper();}

可以使用此格式更改注册表条目值的形式或内容。

Network 项中的每个子项都表示将在登录时重新连接的映射网络驱动器。 RemotePath 项包含连接的驱动器的 UNC 路径。 例如,如果将 E: 驱动器\\Server\Share映射到,则 E 子项中有一个 E 子项HKCU:\Network,E 子项中的 RemotePath 注册表项的值是\\Server\Share

该命令使用 Get-ItemProperty cmdlet 获取 网络 密钥和 Set-ItemProperty cmdlet 的所有子项,以更改每个键中 RemotePath 注册表项的值。 在命令中 Set-ItemProperty ,路径是注册表项的 PSPath 属性的值。 这是表示注册表项而不是注册表项的 Microsoft .NET Framework 对象的属性。 此命令使用 RemotePath 值的 ToUpper () 方法,该方法是字符串 (REG_SZ) 。

由于 Set-ItemProperty 更改每个键的属性, ForEach-Object 因此需要 cmdlet 才能访问该属性。

示例 5:使用$Null自动变量

此示例显示将自动变量管道 $NullForEach-Object cmdlet 的效果。

1, 2, $null, 4 | ForEach-Object {"Hello"}

Hello
Hello
Hello
Hello

由于 PowerShell 将 null 视为显式占位符,因此 ForEach-Object cmdlet 会生成 $Null一个值,就像对管道传递给它的其他对象所做的那样。

示例 6:获取属性值

此示例使用 cmdlet 的 MemberName 参数ForEach-Object获取所有已安装 PowerShell 模块的 Path 属性的值。

Get-Module -ListAvailable | ForEach-Object -MemberName Path
Get-Module -ListAvailable | Foreach Path

第二个命令等效于第一个命令。 它使用 Foreach cmdlet 的 ForEach-Object 别名,并省略 MemberName 参数的名称,这是可选的。

ForEach-Object cmdlet 对于获取属性值非常有用,因为它获取的值而不更改类型,与 Format cmdlet 或 Select-Object cmdlet 不同,后者更改属性值类型。

示例 7:将模块名称拆分为组件名称

此示例演示了将两个点分隔的模块名称拆分为其组件名称的三种方法。

"Microsoft.PowerShell.Core", "Microsoft.PowerShell.Host" | ForEach-Object {$_.Split(".")}
"Microsoft.PowerShell.Core", "Microsoft.PowerShell.Host" | ForEach-Object -MemberName Split -ArgumentList "."
"Microsoft.PowerShell.Core", "Microsoft.PowerShell.Host" | Foreach Split "."

Microsoft
PowerShell
Core
Microsoft
PowerShell
Host

这些命令调用字符串的 Split 方法。 这三个命令使用不同的语法,但它们是等效且可互换的。

第一个命令使用传统语法,其中包括脚本块和当前对象运算符 $_。 它使用句点语法来指定该方法,并使用括号将分隔符参数括起来。

第二个命令使用 MemberName 参数来指定 Split 方法,并使用 ArgumentName 参数将句点 (".") 标识为拆分分隔符。

第三个命令使用 cmdlet 的 ForEach-ObjectForeach 别名,并省略 MemberNameArgumentList 参数的名称,这些参数是可选的。

示例 8:将ForEach-Object与两个脚本块配合使用

在此示例中,我们以位置传递两个脚本块。 所有脚本块都绑定到 Process 参数。 但是,它们被视为已传递到 BeginProcess 参数。

1..2 | ForEach-Object { 'begin' } { 'process' }

begin
process
process

示例 9:对两个以上的脚本块使用ForEach-Object

在此示例中,我们以位置传递两个脚本块。 所有脚本块都绑定到 Process 参数。 但是,它们被视为已传递到 BeginProcessEnd 参数。

1..2 | ForEach-Object { 'begin' } { 'process A' }  { 'process B' }  { 'end' }

begin
process A
process B
process A
process B
end

注意

第一个脚本块始终映射到 begin 块,最后一个块映射到 end 块,两者之间的块均映射到 process 块。

示例 10:为每个管道项运行多个脚本块

如上一示例中所示,使用 Process 参数传递的多个脚本块将映射到 BeginEnd 参数。 若要避免此映射,必须为 BeginEnd 参数提供显式值。

1..2 | ForEach-Object -Begin $null -Process { 'one' }, { 'two' }, { 'three' } -End $null

one
two
three
one
two
three

参数

-ArgumentList

指定方法调用的参数数组。 有关 ArgumentList 行为的详细信息,请参阅 about_Splatting

已在 Windows PowerShell 3.0 中引入了此参数。

Type:Object[]
Aliases:Args
Position:Named
Default value:None
Required:False
Accept pipeline input:False
Accept wildcard characters:False

-Begin

指定在此 cmdlet 处理任何输入对象之前运行的脚本块。 此脚本块仅针对整个管道运行一次。 有关块 begin 的详细信息,请参阅 about_Functions

Type:ScriptBlock
Position:Named
Default value:None
Required:False
Accept pipeline input:False
Accept wildcard characters:False

-Confirm

提示你在运行 cmdlet 之前进行确认。

Type:SwitchParameter
Aliases:cf
Position:Named
Default value:False
Required:False
Accept pipeline input:False
Accept wildcard characters:False

-End

指定在此 cmdlet 处理所有输入对象之后运行的脚本块。 此脚本块仅针对整个管道运行一次。 有关块 end 的详细信息,请参阅 about_Functions

Type:ScriptBlock
Position:Named
Default value:None
Required:False
Accept pipeline input:False
Accept wildcard characters:False

-InputObject

指定输入对象。 ForEach-Object 在每个输入对象上运行脚本块或 operation 语句。 输入一个包含对象的变量,或键入可获取对象的命令或表达式。

InputObject 参数与 一起使用ForEach-Object时,将 InputObject 值视为单个对象,而不是管道命令结果ForEach-Object。 即使该值是作为命令结果的集合(例如 -InputObject (Get-Process))也是如此。 由于 InputObject 无法从对象的数组或集合中返回单个属性,因此,如果你用于 ForEach-Object 对那些在定义属性中具有特定值的对象的对象集合执行操作,则可以在 ForEach-Object 管道中使用,如本主题中的示例所示。

Type:PSObject
Position:Named
Default value:None
Required:False
Accept pipeline input:True
Accept wildcard characters:False

-MemberName

指定要获取的属性或要调用的方法。

允许使用通配符,但仅在生成的字符串解析为唯一值时才有效。 例如,如果运行 Get-Process | ForEach -MemberName *Name,并且有多个成员存在包含字符串名称(如 ProcessNameName 属性)的名称,则命令将失败。

已在 Windows PowerShell 3.0 中引入了此参数。

Type:String
Position:0
Default value:None
Required:True
Accept pipeline input:False
Accept wildcard characters:True

-Process

指定对每个输入对象所执行的操作。 此脚本块针对管道中的每个对象运行。 有关块 process 的详细信息,请参阅 about_Functions

Process 参数提供多个脚本块时,第一个脚本块始终映射到块 begin 。 如果只有两个脚本块,则第二个块将映射到该 process 块。 如果有三个或更多个脚本块,则第一个脚本块始终映射到 begin 块,最后一个块映射到 end 块,两者之间的块全部映射到 process 块。

Type:ScriptBlock[]
Position:0
Default value:None
Required:True
Accept pipeline input:False
Accept wildcard characters:False

-RemainingScripts

指定 Process 参数未采用的所有脚本块。

已在 Windows PowerShell 3.0 中引入了此参数。

Type:ScriptBlock[]
Position:Named
Default value:None
Required:False
Accept pipeline input:False
Accept wildcard characters:False

-WhatIf

显示在此 cmdlet 运行的情况下将会发生什么。 此 cmdlet 未运行。

Type:SwitchParameter
Aliases:wi
Position:Named
Default value:False
Required:False
Accept pipeline input:False
Accept wildcard characters:False

输入

PSObject

你可以通过管道将任何对象传递给此 cmdlet。

输出

PSObject

此 cmdlet 返回由输入确定的对象。

备注

  • ForEach-Object cmdlet 的工作方式与 Foreach 语句非常类似,只不过不能通过管道将输入传递给 Foreach 语句。 有关 Foreach 语句的详细信息,请参阅 about_Foreach

  • 从 PowerShell 4.0 开始, Where 添加了 ForEach 用于集合的方法。 可以在此处阅读有关这些新方法的详细信息 ,about_arrays