关于多个集合的 Powershell foreach
Powershell foreach regarding multiple collections
所以我有一个正在使用的 Powershell 脚本,我想寻求社区的帮助。我必须预先说明,我并不总是最擅长传达我正在尝试做的事情,部分原因是我没有编程经验,所以请耐心等待,如果我用不正确的词来解释我的意思,请问 questions/correct 我均值。
话虽如此,这就是我想要做的事情:
同时递增服务和启动类型:
在服务器 X ($rebootingServer) 上停止服务 A ($services)
在服务器 X ($rebootingServer) 上禁用服务 A ($services)
Given: we know service A is disabled on server Y prior to script running
根据文本文件列表 $startuptypes
在服务器 Y 上启用服务 A
- 在服务器 Y 上启动服务 A
- 冲洗并重复直到 $services 和 $startuptypes 位于每个列表的末尾
所以假设 $services 有:
bits
appmgmt
$startuptypes 有:
Automatic
Manual
我希望分别应用它们(位 > 自动 appmgmt > 手动)
这是我目前所拥有的:
$services = Get-Content "C:\TEMP\services.txt"
$Startuptypes = Get-Content "C:\TEMP\StartupTypes.txt"
$RebootingServer = Read-Host 'Name of the server that you are bringing down'
$FailoverServer = Read-Host 'Name of the server it is failing over to'
#foreach ($service in $services && $Startuptype in $Startuptypes) {
Invoke-Command -ComputerName $RebootingServer -ArgumentList $service - ScriptBlock {param($service) Stop-Service $service}
Start-Sleep -s 3
Invoke-Command -ComputerName $RebootingServer -ArgumentList $service - ScriptBlock {param($service) set-service $service -StartupType Disabled}
Start-Sleep -s 10
Invoke-Command -ComputerName $FailoverServer -ArgumentList $service $StartupType -ScriptBlock {param($service,$startuptype) Set-Service $service -StartupType $startuptype}
Start-Sleep -s 3
Invoke-Command -ComputerName $FailoverServer -ArgumentList $service - ScriptBlock {param($service) Start-Service $service}
Start-sleep -s 10
}
'for each' 语句是我希望它执行的操作的伪代码,但不确定它是否存在或如何相应地编写它。我什至不知道应该怎么称呼它。多个条件?除此之外,我将如何正确地写下我想要完成的事情?感谢您提供任何帮助。
听起来你想枚举对应对中2个集合的元素:在迭代1中,处理集合中的元素1 A 以及集合 B 中的元素 1,...
PowerShell 6- 解决方案:
# Sample collections.
# Note that their counts must match.
$services = 'serviceA', 'serviceB', 'serviceC'
$startupTypes = 'automatic', 'manual', 'disabled '
$i = 0 # helper index var.
foreach ($service in $services) { # enumerate $services directly
# Using the index variable, find the corresponding element from
# the 2nd collection, $startupTypes, then increment the index.
$startupType = $startupTypes[$i++]
# Now process $service and $startupType as needed.
}
PowerShell 7+ 解决方案:
PowerShell 7 基于 .NET Core 3.1 构建,其中 System.Linq.Enumerable.Zip
具有 returns(2 元素) 元组 的重载,这简化了解决方案:
- 警告:对于不同大小的输入集合,一旦较小的集合有 运行 个项目,枚举就会停止。
# Sample collections.
# Note: Due to use of [Linq.Enumerable]::Zip() below:
# * The element counts need *not* match, because pairing stops
# once the shorter collection has run out of elements.
# * However, note that strongly typed type constraint ([string[]]),
# which is required for PowerShell to find the right [Linq.Enumerable]::Zip()
# method overload. You can also *cast* on demand.
[string[]] $services = 'serviceA', 'serviceB', 'serviceC'
[string[]] $startupTypes = 'automatic', 'manual', 'disabled '
# Enumerate the collection in pairs (2-element tuples).
# Note that the tuple elements are always named .Item1 and .Item2.
[Linq.Enumerable]::Zip($services, $startupTypes) | ForEach-Object {
"service: {0}; startup type: {1}" -f $_.Item1, $_.Item2
}
一般来说,请注意,从 7.0 开始,PowerShell 不支持 .NET 扩展方法(这就是为什么此处需要显式使用 [System.Linq.Enumerable]
)以及缺少对调用 通用方法 的全面支持,尽管 GitHub 上有功能请求 - 请参阅 here and here。
以上结果:
service: serviceA; startup type: automatic
service: serviceB; startup type: manual
service: serviceC; startup type: disabled
所以我有一个正在使用的 Powershell 脚本,我想寻求社区的帮助。我必须预先说明,我并不总是最擅长传达我正在尝试做的事情,部分原因是我没有编程经验,所以请耐心等待,如果我用不正确的词来解释我的意思,请问 questions/correct 我均值。
话虽如此,这就是我想要做的事情:
同时递增服务和启动类型:
在服务器 X ($rebootingServer) 上停止服务 A ($services)
在服务器 X ($rebootingServer) 上禁用服务 A ($services)
Given: we know service A is disabled on server Y prior to script running
根据文本文件列表 $startuptypes
在服务器 Y 上启用服务 A
- 在服务器 Y 上启动服务 A
- 冲洗并重复直到 $services 和 $startuptypes 位于每个列表的末尾
所以假设 $services 有:
bits
appmgmt
$startuptypes 有:
Automatic
Manual
我希望分别应用它们(位 > 自动 appmgmt > 手动)
这是我目前所拥有的:
$services = Get-Content "C:\TEMP\services.txt"
$Startuptypes = Get-Content "C:\TEMP\StartupTypes.txt"
$RebootingServer = Read-Host 'Name of the server that you are bringing down'
$FailoverServer = Read-Host 'Name of the server it is failing over to'
#foreach ($service in $services && $Startuptype in $Startuptypes) {
Invoke-Command -ComputerName $RebootingServer -ArgumentList $service - ScriptBlock {param($service) Stop-Service $service}
Start-Sleep -s 3
Invoke-Command -ComputerName $RebootingServer -ArgumentList $service - ScriptBlock {param($service) set-service $service -StartupType Disabled}
Start-Sleep -s 10
Invoke-Command -ComputerName $FailoverServer -ArgumentList $service $StartupType -ScriptBlock {param($service,$startuptype) Set-Service $service -StartupType $startuptype}
Start-Sleep -s 3
Invoke-Command -ComputerName $FailoverServer -ArgumentList $service - ScriptBlock {param($service) Start-Service $service}
Start-sleep -s 10
}
'for each' 语句是我希望它执行的操作的伪代码,但不确定它是否存在或如何相应地编写它。我什至不知道应该怎么称呼它。多个条件?除此之外,我将如何正确地写下我想要完成的事情?感谢您提供任何帮助。
听起来你想枚举对应对中2个集合的元素:在迭代1中,处理集合中的元素1 A 以及集合 B 中的元素 1,...
PowerShell 6- 解决方案:
# Sample collections.
# Note that their counts must match.
$services = 'serviceA', 'serviceB', 'serviceC'
$startupTypes = 'automatic', 'manual', 'disabled '
$i = 0 # helper index var.
foreach ($service in $services) { # enumerate $services directly
# Using the index variable, find the corresponding element from
# the 2nd collection, $startupTypes, then increment the index.
$startupType = $startupTypes[$i++]
# Now process $service and $startupType as needed.
}
PowerShell 7+ 解决方案:
PowerShell 7 基于 .NET Core 3.1 构建,其中 System.Linq.Enumerable.Zip
具有 returns(2 元素) 元组 的重载,这简化了解决方案:
- 警告:对于不同大小的输入集合,一旦较小的集合有 运行 个项目,枚举就会停止。
# Sample collections.
# Note: Due to use of [Linq.Enumerable]::Zip() below:
# * The element counts need *not* match, because pairing stops
# once the shorter collection has run out of elements.
# * However, note that strongly typed type constraint ([string[]]),
# which is required for PowerShell to find the right [Linq.Enumerable]::Zip()
# method overload. You can also *cast* on demand.
[string[]] $services = 'serviceA', 'serviceB', 'serviceC'
[string[]] $startupTypes = 'automatic', 'manual', 'disabled '
# Enumerate the collection in pairs (2-element tuples).
# Note that the tuple elements are always named .Item1 and .Item2.
[Linq.Enumerable]::Zip($services, $startupTypes) | ForEach-Object {
"service: {0}; startup type: {1}" -f $_.Item1, $_.Item2
}
一般来说,请注意,从 7.0 开始,PowerShell 不支持 .NET 扩展方法(这就是为什么此处需要显式使用 [System.Linq.Enumerable]
)以及缺少对调用 通用方法 的全面支持,尽管 GitHub 上有功能请求 - 请参阅 here and here。
以上结果:
service: serviceA; startup type: automatic
service: serviceB; startup type: manual
service: serviceC; startup type: disabled