как удалить фигурные скобки и получить правильный вывод в файле csv

#powershell

#powershell

Вопрос:

Я пытаюсь получить список vm из nutanix с name, ipaddress, Получаемый мной результат включает ip-адрес с фигурными скобками, который выдает вывод в виде System.String[]

Я взял все значения из массива с помощью цикла for, затем экспортировал значения в csv

Сценарий, который я написал, выглядит следующим образом-

 foreach ($vmachine in $vm){
   $obj = "" | Select "vmName", "ipAddresses", "description", "protectionDomainName", "powerState"
   $obj.vmName = $vmachine.vmName
   $obj.ipAddresses = $vmachine.ipAddresses
   $obj.description = $vmachine.description
   $obj.protectionDomainName = $vmachine.protectionDomainName
   $obj.powerState = $vmachine.powerState

   $outArrayVM  = $obj
   $obj =$null
}
$outArrayVM | Export-Csv d:z.csv
  

Ожидаемый результат должен быть таким, как ip-адрес 10.x.x.x , но я получаю @{ipAddresses=System.String[]}

Ответ №1:

Это происходит потому, что $vmachine.ipAddresses является объектом string array. Вам нужно строковое представление этого с контролируемым форматированием. Есть много способов добиться этого. Вот один, который будет объединять несколько IP-адресов (если они существуют) с помощью ; . Если указан только один IP, он будет отображаться без точки с запятой:

 $obj.ipAddresses = $vmachine.ipAddresses -join ";"
  

Вот пример вашего сценария:

 $ip = @("10.1.23.45")
$ip.gettype()

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     Object[]                                 System.Array

$obj.name = "test"
$obj.ip = $ip
$obj

name ip
---- --
test {10.1.23.45}

$obj | convertto-csv

#TYPE Selected.System.String
"name","ip"
"test","System.Object[]"
  

Преобразование ip свойства $obj в строку заставляет PowerShell интерпретировать свойство как строку, а не как коллекцию. Таким образом, обозначение фигурных скобок ( {} ) исчезает.

 $obj.ip = $ip -join ";"
$obj | convertto-csv

#TYPE Selected.System.String
"name","ip"
"test","10.1.23.45"
  

Вот несколько других альтернатив для установки ip значения свойства в виде строки:

 $obj.ip = -join $ip # No join character here. Works best with only one IP.
$obj.ip = $ip[0] # Accesses first element of array $ip, which will be a string. Only works with one IP.
$obj.ip = [string]$ip # Uses string type accelerator to cast $ip as string. This will join multiple IPs with a space between each IP.
  

Объяснение:

При запуске ConvertTo-Csv или Export-Csv свойство объекта ввода преобразуется с помощью ToString() метода. Если ссылочный тип этого свойства объекта ( System.Array в данном случае) не имеет переопределения для ToString() метода, то этот метод вернет полное имя типа свойства. В данном случае этот FQTN равен System.Object[] . Это предсказуемо, если немного покопаться.

При тестировании с [Int32] можно было бы ожидать, что преобразование строки обеспечит строковое представление целочисленных данных, поскольку оно имеет переопределение:

 $int = 1
$int.gettype().fullname

System.Int32

($int | Get-Member).where{$_.Name -eq "ToString"}

   TypeName: System.Int32

Name     MemberType Definition
----     ---------- ----------
ToString Method     string ToString(), string ToString(string format), string ToString(System.IFormatProvider provid...

$int.ToString()
1
$int.ToString().gettype().fullname
System.String
  

При тестировании с помощью [Array] вы бы не ожидали, что преобразование строк обеспечит строковое представление данных массива, поскольку оно не имеет переопределения:

 $arr = [array]1
$arr.gettype().fullname
System.Object[]
([System.Object[]] | Get-Member -Static).where{$_.name -eq "ToString"}

$arr.toString()
System.Object[]
  

Смотрите раздел Экспорт-Csv и объект.Метод toString для дополнительных пояснений и примеров.