как выбрать только одно свойство из массива «результатов» из команды Azure «список групп az в powershell»? - PullRequest
0 голосов
/ 06 ноября 2019

Я пытаюсь выбрать только одно свойство из массива «результата» (объектов?), Которые возвращаются из команды Azure az group list в powershell?

Я знаю, что это звучит тривиально, но вот где это становится странным, и я надеюсь, что есть простое объяснение.

Если я запускаю команду Azure az group list -o table (после успешного входа в системуиспользуя az login) Я получаю следующий типичный ответ

PS src> az group list -o table             
Name              Location    Status
----------------  ----------  ---------
group0            westeurope  Succeeded
group1            westeurope  Succeeded
group2            uksouth     Succeeded
group3            westeurope  Succeeded
group4            westeurope  Succeeded
group5            westeurope  Succeeded
group6            westeurope  Succeeded
group7            uksouth     Succeeded
group8            westeurope  Succeeded
group9            westeurope  Succeeded

, однако, если я пытаюсь выбрать только свойство Name, выполнив

az group list |выберите -p имя

Затем я получаю около 2 экранов, заполненных пустыми строками, но ничего не отображается. Итак, вопрос в том, что не так с командой выше? И как мне это исправить?

Я попытался в следующих экспериментах покопаться в точных типах возвращаемых объектов и получить некоторые результаты, которые я не понимаю. Я надеюсь, что это будет иметь смысл для тех, у кого больше опыта работы с Azure и PowerShell.

Вот шаги, которые очень легко воспроизвести проблему, если у вас есть учетная запись Azure.

  1. Запустите PowerShell, например, на Mac-терминале, введите pwsh
  2. , войдите в Azure az login
  3. введите az group list -o table

обратите внимание, что список возвращается и правильно отформатирован.

type az group list | select -p name

Наблюдайте за несколькими экранами, полными пустых строк. без текста.

почесать голову и удивиться, что только что произошло? (ухмыляясь)

УСТРОЙСТВО ТОЛЩИНЫ

az group list само по себе возвращает несколько экранов, полных этого

[
 ... lots of these ...
 {
    "id": "/subscriptions/this-is-super-wierd-i-cant-select-name-prop/resourceGroups/spikes",
    "location": "westeurope",
    "managedBy": null,
    "name": "spikes",
    "properties": {
      "provisioningState": "Succeeded"
    },
    "tags": {},
    "type": null
  }
]

однако, (az group list).getType() возвращает

PS src> (az group list).getType()

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

и, наконец, мы надеемся, что последние 2 фрагмента головоломки

PS src> (az group list)[0].getType()

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     String                                   System.Object

, поэтому типы возврата из az group list выглядят как array of objects илиможет быть, это массив object[], мой PowerShell здесь неестественный. Поэтому для двойной проверки я запрашиваю первые 10 элементов этого массива, выполняя ... (az group list)[0..10], и это возвращает причудливо 10 strings!. Хорошо, я знаю, что это должно быть 10 строк, только потому, что это компьютер, и если это то, чем он является, то это то, чем он является на самом деле. Я просто не понимаю, почему.

[
  {
    "id": "/subscriptions/12345678-1234-1234-1234-123456789012/resourceGroups/somegroup",
    "location": "westeurope",
    "managedBy": null,
    "name": "admin",
    "properties": {
      "provisioningState": "Succeeded"
    },
    "tags": {},
    "type": null

Итак, говоря коротко, хочу ли я знать, как выбрать одно свойство из результата лазурного запроса? В моем случае я просто хочу отобразить имена всех моих групп ресурсов.

Это az group list | select -p name должно работать, но не работает, и я хотел бы знать, как это сделать правильно, и в процессе выяснить, почему это не работает, и мы все можем кое-что узнать оAzure и PowerShell в процессе, и жизнь может быть великолепной!

Люблю вас всех, Алан

Ответы [ 2 ]

2 голосов
/ 07 ноября 2019

Давайте работать через это. Когда мы указываем -o table, например:

az group list -o table

Мы говорим Azure PowerShell CLI взять полученный JSON-контент и отформатировать его в удобную для нас таблицу. Как правило, мы не хотим работать с RAW JSON и не хотим работать с отформатированными таблицами. Работа со строковыми массивами в PowerShell также не очень удобна. В PowerShell мы хотим работать с «красивыми» легкими объектами. Итак, давайте посмотрим на другие способы получения нашей информации. Давайте возьмем ваш пример и просто сохраним его в переменной, на которую мы можем посмотреть:

$GroupList = az group list

Тогда, если мы посмотрим на тип:

PS C:\> $GroupList.GetType()

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

Действительно, у нас есть массивобъекты. Они должны быть массивом наших групп ... верно? ... ну нет. Это не то, что вы думаете. Если мы посмотрим на размер массива и вернем первые несколько элементов массива, мы увидим, что происходит:

PS C:\> $GroupList.Count
125
PS C:\Temp> $GroupList[0..2]
[
  {
    "id": "/subscriptions/12345678-1234-1234-1234-123456789012/resourceGroups/somegroup",

Ну, это не то, что мы хотели. Массив слишком велик ... и просмотр содержимого показывает, что на самом деле мы имеем массив каждой строки текста JSON . Это означает, что выполнение:

az group list | select -p name

или:

$GroupList | select -p name

Говорит, перебирает массив и выводит только свойство «Имя». Поскольку свойство «Имя» не существует в текстовой строке, оно просто выводит пустую строку. Поскольку в тексте несколько сотен строк, мы получаем несколько сотен строк пробелов.

Так почему PowerShell принимает входные данные и разбивает их на массив строк, разделенных новыми строками? Разве это не сложно использовать? Разве это не "отличный" способ обработки текста в формате JSON? Почему бы нам просто не получить одну гигантскую нить? Разве это не легче обрабатывать и анализировать? В чем причина такой странности?

Что касается PowerShell, то необходимость поддержки конвейеров приводит к принятию решений о том, как мы выводим объекты:

«Основная цель ... способ гарантировать, что результатом выполнения конвейера всегда будет индексируемая коллекция. " Цитата

Вот почему мы получаем выводимый массив объектов (см. Ответ @ mklement0 здесь для более подробного обсуждения ) для поддержки операций конвейера. И если мы посмотрим, как текстовые файлы читаются и записываются, мы можем точно указать, почему мы получаем именно этот кашель Программист кашель удобство кашель ... я имею в виду странность.

Чтобы все настроить, мы можем направить вывод напрямую в текстовый файл:

az group list | Out-File -FilePath List.json

Ух, подожди секунду, почемуэто просто работа? (В подобных ситуациях я хотел бы сказать, что PowerShell выполняет Magic! ). Не нужно ли нам возиться с циклическим перебором массивов, добавляя строки, заканчивающиеся символами новой строки, чтобы получить один гигантский непрерывный блок текста, который заканчиваетсяс EOF, и точно соответствует нашему желаемому текстовому файлу?

Упрощенная причина того, что на самом деле происходит? Ну, из-за удобства программиста, Out-File берет массив строк, перебирает его и делает простое File.WriteLine() для каждой строки (неплохо для 3 строки для цикла!). Следовательно, мы только что сгенерировали хороший форматированный текстовый файл JSON с символами новой строки, без проблем. Читая это обратно:

PS C:\> $ListFromFile = Get-Content .\List.json
PS C:\> $ListFromFile.GetType()

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


PS C:\> $ListFromFile.Count
125

Делает обратное. Он берет файл, делает File.ReadLine(), добавляет строки в массив и возвращает его. Вот почему мы получаем массив объектов, содержащий строки.

Теперь, что мы действительно хотим? Ну, мы знаем с самого начала, мы не хотим работать с одной гигантской строкой, и мы особенно не хотим работать со строками в массиве объектов, что мы хотимработать с это хороший нативный PSCustomObject, к которому мы можем получить доступ. Это то, с чем лучше всего работает PowerShell, это то, с чем мы лучше всего работаем. Таким образом, мы просто должны преобразовать наши (большие воздушные кавычки) «ввод текста», который, как мы знаем, отформатирован как JSON, и преобразовать его в объект:

$List = $GroupList | ConvertFrom-Json

И с учетом количества и свойств:

PS C:\> $List.Count
10
PS C:\> $List.GetType()

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


PS C:\> $List[0].GetType()

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     False    PSCustomObject                           System.Object

Мы видим, что счетчик теперь соответствует количеству групп, и типы больше не являются массивом строк, а являются действительными объектами. Итак ... Теперь , мы можем начать сортировку и выбрать:

PS C:\> $List | select -Property Name

Name            
----
group0
group1
group2
group3
group4
group5
group6
group7
group8
group9

И мы получим вывод, который мы действительно хотели.

1 голос
/ 07 ноября 2019

вау, столько текста для чего-то простого:

az group list --query '[].name' -o tsv
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...