Powershell: экспорт пользовательского объекта в файл CSV — извлечение одного значения свойства с помощью Select-Object

Я написал скрипт, который создает пользовательский объект и экспортирует его в файл CSV:

$reg = Get-ItemProperty HKLM:\SOFTWARE\McAfee\DLP\Agent | Select-Object agentversion

$date = Get-ItemProperty 'C:\Program Files\McAfee' | Select-Object {$_.LastWriteTime} 

$date86 = Get-ItemProperty 'C:\Program Files (x86)\McAfee'| Select-Object {$_.LastWriteTime}

New-Object -TypeName pscustomobject -Property @{
  "Number1"=$reg
  "Number2"=$date86
  "Number3"=$date } | export-csv -Path C:\****\desktop\stuff.csv -NoTypeInformation

и строка данных в результирующем файле CSV:

"@{AgentVersion=9.4.112.22}","@{$.LastWriteTime=5/6/2016 6:02:32}","@{$.LastWriteTime=7/5/ 2016 20:34:01}"

Можно ли избавиться от нежелательных оберток @{<name>=...}?


person C.Kelly    schedule 11.07.2016    source источник


Ответы (2)


Выражение:

Select-Object {$_.LastWriteTime}

выводит объект с одним свойством с именем $_.LastWriteTime. Самый простой способ исправить это — использовать параметр -ExpandProperty, который будет выводить только то значение, которое вас интересует. Например:

$date86 = Get-ItemProperty 'C:\Program Files (x86)\McAfee'|
            Select-Object -ExpandProperty LastWriteTime 

Обратите внимание, что я также удалил блок сценария из команды Select-Object, так как в этом не было необходимости.

person zdan    schedule 12.07.2016

Чтобы дополнить полезный ответ zdan[1] альтернативами:

Если вам просто нужно значение свойства данного объекта, просто оберните команду в (...) и используйте .<propertyName>:

(Get-ItemProperty 'C:\Program Files\McAfee').LastWriteTime # returns a [datetime] instance

В PSv3+ описанное выше также работает с командами, возвращающими несколько элементов (массивов), и в этом случае выводится массив значений отдельных свойств входных элементов — эта функция называется перечисление элементов.


В PSv3 появился сокращенный синтаксис для % / ForEach-Object (а также ? / Where-Object), который можно использовать и здесь:

Get-ItemProperty 'C:\Program Files\McAfee' | % LastWriteTime # ditto

Это эквивалент более подробного (который также работает в PSv2-):

Get-ItemProperty 'C:\Program Files\McAfee' | % { $_.LastWriteTime }

Эти две формы синтаксиса на основе конвейера медленнее, но имеют два преимущества:

  • Большие входные коллекции лучше обрабатывать в конвейерах один за другим, чтобы поддерживать постоянное использование памяти (если это возможно; если вам нужно собрать весь вывод в памяти, нет никакого преимущества).

  • Этот синтаксис однозначно ссылается на свойство отдельного элемента, а не на свойство коллекции в целом.

    • E.g., (Get-ChildItem -File C:\Windows).Length returns the count of files in C:\Windows, because Length is interpreted as the collection's (array's) property;
      by contrast, Get-ChildItem -File C:\Windows | % Length returns an array of the individual files' .Length (file-size) property values.

Наконец, в PSv4+ вы также можете использовать .ForEach() метод коллекции, который не использует конвейер и, следовательно, работает быстрее (хотя и немного медленнее, чем перечисление членов), но, как и перечисление членов, требует, чтобы входная коллекция находилась в памяти полностью :

(Get-ItemProperty 'C:\Program Files\McAfee').ForEach('LastWriteTime')

[1] Краткий обзор Select-Object поведение:

  • Select-Object [-Property] <string[]> возвращает пользовательский объект для каждого входного объекта, содержащий только указанные свойства; даже если указано только одно свойство, результаты представляют собой настраиваемые объекты с этим единственным свойством, а не сами значения свойства.

  • В отличие от этого, использование -ExpandProperty <string> вместо этого возвращает значение заданного одиночного свойства из каждого входного объекта (набранного как есть).

Простой пример: извлеките значение свойства Year из вызова Get-Date:

# WRONG: with (implied) -Property
PS> $val = Get-Date | Select-Object Year; "$val"
@{Year=2018}  # !!
# A custom object with a Year property was returned and the above is its
# string representation, the equivalent of:
#      "$([pscustomobject] @{ Year = 2018 })"

# CORRECT: with -ExpandProperty
PS> $val = Get-Date | Select-Object -ExpandProperty Year; "$val"
2018  # OK: -ExpandProperty extracted just the property's *value*
person mklement0    schedule 12.07.2016