PowerShell/CLI:具有多个数组的“Foreach”循环

Posted

技术标签:

【中文标题】PowerShell/CLI:具有多个数组的“Foreach”循环【英文标题】:PowerShell/CLI: "Foreach" loop with multiple arrays 【发布时间】:2014-10-01 05:50:03 【问题描述】:

我有一个 PowerCLI 脚本,它可以关闭 VM、更改其内存和 cpu,然后重新打开它。我已经修改了脚本以利用变量。这一切都很完美。

我现在正在尝试修改脚本以利用数组,以便在众多虚拟机中循环。关闭和打开虚拟机电源的脚本部分完美运行。

我遇到的问题是在 foreach 循环中使用来自两个数组的变量。

对于 $vm_name 中的每个 VM,我需要设置在 $memory_gb 中找到的相应内存量。

这就是我所拥有的(它目前为所有虚拟机设置了相同数量的内存(“1”)....

$vm_name = @("OMAC-SBXWIN7AJM", "OMAC-SBXWIN2012R2AJM", "OMAC-SBXWIN2008R2AJM")
$memory_gb = 2,4,4

# SET THE VM MEMORY
Write-Host 'NOW SETTING THE VM MEMORY'
foreach ($objItem in $vm_name)
Set-VM -VM $vm_name -MemoryGB 1 -confirm:$false 
Break

http://i.stack.imgur.com/E9hfY.png

...我尝试在第一个循环中嵌套第二个 foreach 循环,但无济于事。

如何编写脚本让 $vm_name 中的每个 VM 获取在 $memory_gb 中找到的相应内存量?

【问题讨论】:

【参考方案1】:

您可以使用 Zip 功能:

function Zip($a1, $a2) 
    while ($a1) 
        $x, $a1 = $a1
        $y, $a2 = $a2
        [tuple]::Create($x, $y)
    

用法:

zip 'a','b','c' 1,2,3 |% $_.item1 + $_.item2

结果:

a1
b2
c3

【讨论】:

@js2010 为以后的读者清除它:$x, $a1 = $a1 语法是解压数组的下一个成员,而不是保留手动迭代器 $i 或类似的【参考方案2】:

您有 2 个选项。首先(不是我建议的)是一个 For() 循环。它会是这样的:

For($I=0;$I -lt $vm_name.count;$I++)
    Set-VM -VM $vm_name[$I] -MemoryGB $memory_gb[$I] -confirm:$false

更好的方法是将其放入带有 VMName, Memory 之类的标头的 CSV 中,然后列出每个 VM 和您想要的内存。然后运行类似:

Import-CSV C:\Path\To\File.CSV | ForEachSet-VM -VM $_.VMName -MemoryGB $_.memory -confirm:$false

【讨论】:

将其放入数据文件中非常聪明,脱帽致敬。 这非常有效。谢谢!我肯定会使用 .CSV,因为我最终会修改许多机器。 这行得通,但我得到了这个错误.... Set-VM:无法将参数“MemoryGB”绑定到目标。异常设置“MemoryGB”:“对象引用未设置为对象的实例。”在 U:\How To\PowerCLI\Test.ps1:8 char:36 + Set-VM -VM $vm_name[$i] -MemoryGB $memory_gb[$i] -confirm:$false + ~~~~~~~ ~~~~~~~ + CategoryInfo : WriteError: (:) [Set-VM], ParameterBindingExcept ion + FullyQualifiedErrorId : ParameterBindingFailed,VMware.VimAutomation.ViCo re.Cmdlets.Commands.SetVM 既然它起作用了,那么错误真的重要吗? 这可能是因为我使用 -le 而不是 -lt 所以它试图迭代第 4 个 VM/内存集。我真的希望您使用第二个选项,所以我没有像第一个选项那样密切关注。我会尽快更新答案以纠正该问题。【参考方案3】:

另一个更紧凑的解决方案是使用哈希表:

$vms = @"OMAC-SBXWIN7AJM" = 2; "OMAC-SBXWIN2012R2AJM" = 4; "OMAC-SBXWIN2008R2AJM" = 4

# SET THE VM MEMORY
Write-Host 'NOW SETTING THE VM MEMORY'
foreach ($vm in $vms.getEnumerator())
    Set-VM -VM $vm.Name -MemoryGB $vm.Value -confirm:$false 

【讨论】:

这也对我有用。谢谢!我没有考虑过使用哈希表。【参考方案4】:
$vm_name = @("OMAC-SBXWIN7AJM", "OMAC-SBXWIN2012R2AJM", "OMAC-
SBXWIN2008R2AJM")
$memory_gb = 2,4,4

# SET THE VM MEMORY
Write-Host 'NOW SETTING THE VM MEMORY'
foreach ($objItem in $vm_name)

    Set-VM -VM $vm_name -MemoryGB $memory_gb[$vm_name.indexOf($objItem)] -confirm:$false 
    Break

只要两个数组大小相同,这将起作用。

【讨论】:

你先生是一位绅士和学者,我无法弄清楚如何将两个数组类型变量传递给一个 foreach 循环,而不是每次都在其他数组项上执行每个数组项。所以应该运行 4 次循环的东西正在执行 16 次。但这部分救了我:[$vm​​_name.indexof($objItem)] Index of 是一个非常聪明的解决方案。【参考方案5】:
$vm_name = @("OMAC-SBXWIN7AJM", "OMAC-SBXWIN2012R2AJM", "OMAC-SBXWIN2008R2AJM")
$memory_gb = (2,4,4)

# SET THE VM MEMORY
Write-Host 'NOW SETTING THE VM MEMORY'
for( $i = 0; $i -lt $vm_name.length; $i++) 
  $vm = $vm_name[$i]
  $gb = $memory_gb[$i]
  write-host setting $vm to $gb GB ...
  Set-VM -VM $vm -MemoryGB $gb -confirm:$false 

您只需要确保两个数组的长度相同。

【讨论】:

@JamesMcCallister:我很受宠若惊,但在 SO 上,感谢通常以赞成和/或接受最佳答案的形式表达 :-)

以上是关于PowerShell/CLI:具有多个数组的“Foreach”循环的主要内容,如果未能解决你的问题,请参考以下文章

powershell inline 在竹子中失败,但从 windows powershell CLI 传递

PowerShell CLI 获取VM信息

知道如何使用 powershell/cli 或任何其他方式获取/查询其中创建了 Queue/table/file/blob 的存储帐户列表吗?

具有 MagicalRecord 的多个数据模型

具有类数组的 SKNode 子级

在Python中运行Powershell命令(SyntaxError:无效语法)