Гистограмма Powershell не записывается в файл как ожидалось - получайте только строки "System.Collections"

Может кто-нибудь объяснить Почему мои первые примеры не работают, и почему добавление в ForEach-Object решает проблему? Спасибо заранее!


Я проанализировал возвращение из команды в хэш-таблицу (образец в конце сообщения) и хочу записать эту информацию в файл как часть моей обработки. Я знаю, что $ht.GetEnumerator() | Sort-Object Name вернет полный хеш для отображения, сортировки. Однако, когда я пытаюсь отправить файлы в файл, он прерывается.

$ht | Add-Content log.txt

регистрирует только одну строку System.Collections.Hashtable. Итак, я также пробовал

$ht.GetEnumerator() | Sort-Object Name | Add-Content log.txt 

и в итоге появятся строки

System.Collections.DictionaryEntry
System.Collections.DictionaryEntry
System.Collections.DictionaryEntry

Итак, я попытался выполнить цикл и обработать каждый отдельно с помощью

foreach ($key in $ht.keys) {
Add-Content log.txt "$key : $ht.$key" }

и в итоге

Server address : System.Collections.Hashtable.Server address
Client address : System.Collections.Hashtable.Client address
User name : System.Collections.Hashtable.User name

Решено:

$ht.GetEnumerator() | Sort-Object Name |
ForEach-Object {"{0} : {1}" -f $_.Name,$_.Value} |
Add-Content log.txt 

Для справки, образец хеш-таблицы:

$ht = @{
    "Server address" = "server.net";
    "Client address" = "10.20.121.153";
    "User name" = "myuser"
}

Ответ 1

Отвечая на причину, вы, очевидно, имеете решение:)

В первом примере

$ht | Add-Content log.txt

PowerShell принимает $ht и пытается каким-то образом преобразовать его в строку, чтобы его можно было сохранить через Add-Content. Поскольку для хеш-таблицы нет конверсии, из преобразования возвращается только имя типа. То же, что, например, new-Object Random|Add-Content d:\log.txt. Опять же, записывается только имя типа.

Далее

$ht.GetEnumerator() | Sort-Object Name | Add-Content log.txt 

аналогичен. GetEnumerator возвращает объект, который используется для итерации; возвращаются объекты типа System.Collections.DictionaryEntry. Опять же, преобразование в строку отсутствует, поэтому имена типов возвращаются.

Лично я считаю, что PowerShell должен быть достаточно умным и помогать здесь. Вопрос: "как?". Дизайнеры, вероятно, не хотели жестко кодировать вывод. Это может быть "{key}: {value}" или "{key} = {value}", или "{key}/{value}", или... Формат не ясен, поэтому они оставили его для нас, чтобы решить и отформатировать, как вы сделали это с помощью инструкции foreach.

Ответ 2

Я согласен с mjolinor... просто недостаточно очков для голосования... плюс я добавлю, что вам не нужен GetEnumerator

$ht | out-string | add-content log.txt

сделает это.

Ответ 3

Ваш первый пример не работает, или лучше, частично работает, потому что вы пытаетесь получить значение свойства внутри строки. Обычно внутри строк анализатор может разрешать только прямые переменные (например, $key). Чтобы разрешить более сложную переменную, вам нужны скобки.

Для цикла это должно работать:

foreach ($key in $ht.keys) {
Add-Content log.txt "$key : $($ht.$key)" }

или даже лучше

$ht.keys | %{ Add-Content log.txt "$_ : $($ht.$_)" }

Ответ 4

Как вы можете видеть в документации Microsoft, хеш-таблица представляет собой просто набор пар имя-значение.

Итак, $ht действительно System.Collections.Hashtable состоит из System.Collections.DictionaryEntry.

Хороший способ его использования -

foreach ($i in $ht.keys)
{
  add-content log.txt ("{0} {1}" -f $i, $ht[$i])
}

Ответ 5

Как насчет:

 $ht.GetEnumerator() | Sort-Object Name | out-string | Add-Content log.txt