【问题标题】:Output of array of arrays in Powershell / Powercli gets truncated w/ellipsesPowershell / Powercli 中数组的输出被截断并带有省略号
【发布时间】:2015-04-17 22:09:43
【问题描述】:

我的脚本的目的是从我们的 vcenter 获取整个虚拟机列表,检查它们是否有 DNS 条目 - 如果 dns 条目为空,则输出虚拟机名称和相应的 IP 地址。很简单,但是我在将 VM 名称数组与 IP 地址数组结合起来时遇到了麻烦。这就是我的意思:

$mainArray = @()
$vmArray = @()
$ipArray = @()

$vms = Get-VM | select Name, @{N="DnsName"; E={$_.ExtensionData.Guest.Hostname}}, @{N="IPAddress"; E={$_.Guest.IPAddress[0]}}

foreach ($vm in $vms)
{
   $dnsname = $vm.DnsName
   $ipaddr = $vm.IPAddress
   $vmname = $vm.Name

    if (!$vm.DNSName) #if DNS name is null
    {
       $vmArray += $vmname
       $ipArray += $ipaddr
     }
}       

$item = New-Object PSObject
$item | Add-Member -type NoteProperty -Name 'VM Name' -Value $vmArray
$item | Add-Member -type NoteProperty -Name 'IP Address' -Value $ipArray

$mainArray += $item

$mainArray | ft -wrap -autosize

这会输出彼此相邻的两列,但输出用逗号分隔并用椭圆截断。我知道有更好的方法可以做到这一点,所以我愿意接受建议。也很想知道如何使这项工作只是为了我自己的理解。感谢大家的帮助。

【问题讨论】:

  • 您只关心屏幕上的输出吗?我猜数据在那里。您只是看到了 PowerShell 向控制台显示数组的作用。数据还在。这只会生成一行吗?您是否期望您的表格中有更多结果?
  • 对不起,我应该更具体一些。是的,数据看起来不错,是的,它只生成一行。有很多数据(超过 300 台虚拟机),并且在第 5 台虚拟机处被截断。我希望将其输出为显示在两个干净列中的列表(每行一个值)。一列用于 VM 名称,另一列用于对应的 IP 地址。我想我已经接近了,但不确定我是否会以最好的方式解决这个问题。

标签: arrays powershell powercli


【解决方案1】:

您的主要问题是您在循环之外填充了一个数组。我现在无法访问我面前的 PowerCLI,但我们应该能够删除大部分代码,因为它似乎是多余的和不必要的。在$vms 被声明后继续

$vms | Where-Object{!$_.DNSName} | ForEach-Object{

    New-Object PSObject -Property @{
        'VM Name' = $_.Name
        'IP Address' = $_.IPAddress
    }
} | ft -wrap -autosize

之前你做了一个两个数组。一个用于名称,另一个用于 ips。然后你拿了这两个数组并用这两个属性制作了一个对象。我用Where-Object{!$_.DNSName} 消除了对if 语句的需求。现在所有正在处理的对象都是您想要的。

您真的可以使用相同的逻辑在一/两行中做到这一点。

Get-VM | Select @{N='VM Name';E={$_.Name}}, @{N="DnsName"; E={$_.ExtensionData.Guest.Hostname}}, @{N="IP Address"; E={$_.Guest.IPAddress[0]}} |
    Where-Object{!$_.DNSName} | Select "VM Name","IP Address" | Format-Table -wrap -autosize

同样,我无法测试,但它应该可以工作。如果有任何错误,它们应该很容易纠正。假设我首先弄清楚了你的问题。

关于省略号

PowerShell 有一个变量$FormatEnumerationLimit,它控制在控制台输出中显示多少数组元素。 TechNet上有一篇很好的文章讨论它

默认$FormatEnumerationLimit设置为4

【讨论】:

  • 感谢马特的回复。我看到了它是如何工作的,并且它可以更有效地完成它。这是一个更好的解决方案。但是,仅出于我自己的理解,您能否解释一下我如何在两个单独的干净列中手动显示两个数组($vmarray 和 $iparray)?
  • @user1932885 不确定我是否理解,因为我的回答试图向您展示这一点。一栏很简单,只需键入$vmarray$iparray。 PowerShell 最适用于对象,因此按照您的尝试创建对象是可行的方法。否则你可以操纵字符串输出,但这不是必需的而且很混乱。
  • 关于操纵字符串输出的最后一部分是我很好奇的。使用原始脚本,我可以在单独的列中显示输出,但输出是逗号分隔和截断的。有没有办法处理这个?我知道你给了我一个更好的解决方案,但我只是想了解为什么我的原始脚本无法达到相同的结果。
  • @user1932885 我更新了答案以涵盖我认为您正在寻找的内容
【解决方案2】:

Matt,我之前发现了该链接,但没有发现它很有帮助,因为它使输出出现乱码并且不会按行分解值。这就是我能够使原始脚本工作的方式:

$i=0

write-output $vmArray |
foreach {
new-object psobject -property @{
                                VMName = $_
                                IPAddress = $ipArray[$i++]
                             }
    }   | ft -auto -wrap

相当非传统,但确实有效。确实应该有一种更简单的方法来并排组合数组,但我离题了。非常感谢马特。

更新:这可能更传统:

    For($i=0;$i -lt $vmArray.Count;$i++)
    {
    $item = New-Object PSObject
    $item | Add-Member -type NoteProperty -Name 'VM Name' -Value    $vmArray[$i]
    $item | Add-Member -type NoteProperty -Name 'IP Address' -Value $ipArray[$i]
    $mainArray += $item
      }

$mainArray | ft -wrap -autosize 

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-08-18
    • 2019-08-29
    • 2013-07-17
    • 1970-01-01
    • 1970-01-01
    • 2016-10-18
    • 2015-03-11
    • 2012-11-23
    相关资源
    最近更新 更多