Nano Hash - криптовалюты, майнинг, программирование

Создайте словарь из списка строк, используя разделитель с Ansible

У меня есть вложенный список строк, которые я пытаюсь преобразовать в словарь. Список кажется в разумном формате, но мой словарь перезаписывается каждый раз, когда я добавляю к нему.

Исходный список:

TASK [test first_list] **********************************************************************************************************************************************************************************************************************************************************************************************************
ok: [node11] => {
    "first_list": [
        [
            "DEVNAME: /dev/sanstorage/node11-data103-2fd31b74e1ef5a8006c9ce9000b10399f",
            "UUID: 2751719f-d1a2-49b0-9e42-3d686c90d2e6",
            "TYPE: xfs"
        ],
        [
            "DEVNAME: /dev/sanstorage/node11-data104-2e81f1279171dce656c9ce9000b10399f",
            "UUID: 6a6265d6-b103-471e-9e25-e8cc5f5585a8",
            "TYPE: xfs"
        ],
        [
            "DEVNAME: /dev/sanstorage/node11-data102-2e385a327788d866e6c9ce9000b10399f",
            "UUID: 8c52d974-8584-4aa6-89b8-f1e1db016118",
            "TYPE: xfs"
        ],
        [
            "DEVNAME: /dev/sanstorage/node11-data101-241afe5ab93b5c0ee6c9ce9000b10399f",
            "UUID: 94b56164-6717-4b82-8f11-86fd94a39672",
            "TYPE: xfs"
        ],
        [
            "DEVNAME: /dev/sanstorage/node11-data100-25626d38d4c4239456c9ce9000b10399f",
            "UUID: 55a1a388-fe0a-4dd0-980a-a10c5317952e",
            "TYPE: xfs"
        ],
        [
            "DEVNAME: /dev/sanstorage/node11-data114-231d2661b7ab88f8f6c9ce9000b10399f",
            "UUID: f87ad708-1d12-41a5-9441-d32a97b5318c",
            "TYPE: ext4"
        ],
        [
            "DEVNAME: /dev/sanstorage/node11-data115-2d3a824975e90550f6c9ce9000b10399f",
            "UUID: b8b79886-9710-4205-900b-7b9d7d4ad933",
            "TYPE: ext4"
        ],
        [
            "DEVNAME: /dev/sanstorage/oneview-FA-data8165-284392eae1ad17d846c9ce9000b10399f",
            "UUID: c5a43057-676e-49b7-b2a9-b53a40f7010b",
            "TYPE: xfs"
        ],
        [
            "DEVNAME: /dev/sanstorage/oneview-FA-data3420-2e262703236f9b7046c9ce9000b10399f",
            "UUID: 1a70c187-9364-4f48-92f8-f9b9dec9824f",
            "TYPE: xfs"
        ],
        [
            "DEVNAME: /dev/sanstorage/node11-data112-2464954fd324508e66c9ce9000b10399f",
            "UUID: 2238a12e-2ca1-466e-8617-11051e1d612e",
            "TYPE: ext4"
        ],
        [
            "DEVNAME: /dev/sanstorage/node11-data111-25bb14827531149456c9ce9000b10399f",
            "UUID: db37479f-80b0-46b2-85e0-aef679bea164",
            "TYPE: ext4"
        ],
        [
            "DEVNAME: /dev/sanstorage/node11-data105-28ac6825aa80520d46c9ce9000b10399f",
            "UUID: e987fc7c-9a4f-46ea-91f0-4d5f37d3421e",
            "TYPE: xfs"
        ],
        [
            "DEVNAME: /dev/sanstorage/node11-data113-2177c50c4dd5063506c9ce9000b10399f",
            "UUID: 36c1194d-ac4f-4cee-8688-353974cb6be0",
            "TYPE: ext4"
        ]
    ]
}

Отсюда я пытаюсь сформировать словарь, но в конце сохраняется только последняя запись списка:

TASK [test final_list] **********************************************************************************************************************************************************************************************************************************************************************************************************
ok: [node11] => {
    "final_list": {
        "DEVNAME": "/dev/sanstorage/node11-data113-2177c50c4dd5063506c9ce9000b10399f",
        "TYPE": "ext4",
        "UUID": "36c1194d-ac4f-4cee-8688-353974cb6be0"
    }
}

В идеале это выглядело бы примерно так, я предполагаю, что мне нужно вложить словарь в список?

    "final list": [
        {
            "DEVNAME: /dev/sanstorage/node11-data103-2fd31b74e1ef5a8006c9ce9000b10399f",
            "UUID: 2751719f-d1a2-49b0-9e42-3d686c90d2e6",
            "TYPE: xfs"
        },
        {
            "DEVNAME: /dev/sanstorage/node11-data104-2e81f1279171dce656c9ce9000b10399f",
            "UUID: 6a6265d6-b103-471e-9e25-e8cc5f5585a8",
            "TYPE: xfs"
        },
        {
            "DEVNAME: /dev/sanstorage/node11-data102-2e385a327788d866e6c9ce9000b10399f",
            "UUID: 8c52d974-8584-4aa6-89b8-f1e1db016118",
            "TYPE: xfs"
        },
... snip ...

Ниже приведена важная часть учебника:

    - set_fact:
        first_list: "{{ first_list | default([]) + [disk_data.split('\n')] }}"
      vars:
        disk_data: '{{ item.stdout }}'        
      with_items: "{{ disk_check.results }}"

    - name: test first_list
      debug:
        var: first_list
    
    - set_fact: final_list:{}

    - set_fact:
        final_list: "{{ final_list | default([]) | combine(dict([ item.partition(':')[::2]|map('trim')])) }}"
      with_items: "{{ first_list }}"

    - name: test final_list
      debug:
        var: final_list

Мысли?

02.04.2021

  • combine для dict, вы каждый раз переопределяете значения, так как это одни и те же ключи. Попробуйте заменить «| combine(...)» простым «+ ...» 02.04.2021

Ответы:


1

TL;DR

- debug:
    msg: "{{ disk_check.results | map(attribute='stdout') | map('from_yaml') | list }}"

Вы не предоставили начальную задачу, которая возвращает disk_check. Исходя из вашего использования в вашем примере, я буду считать само собой разумеющимся, что это задача shell или command, используемая в цикле.

Между тем, вы по-прежнему предоставили достаточно информации, чтобы мы могли избежать проблемы x/y. Ваш вопрос в основном заключается в том, как я могу разделить строку на разделители и использовать результат для создания словаря? где то, что вы действительно хотите, больше. Как я могу разобрать строку, представляющую yaml dict, в фактический dict?

Начать с

- set_fact:
    first_list: "{{ first_list | default([]) + [disk_data.split('\n')] }}"
  vars:
    disk_data: '{{ item.stdout }}'        
  with_items: "{{ disk_check.results }}"

Это просмотр всех результатов вашей команды, разбиение stdout на новую строку и добавление этого списка в список верхнего уровня.

Поскольку выходные данные shell/command содержат атрибут stdout_lines< /a> и что мы можем извлекать атрибуты из списка dicts с помощью jinja2 map filter, его можно заменить за один раз, вообще не запуская задачу, с помощью следующего выражения jinja:

"{{ disk_check.results | map(attribute='stdout_lines') | list }}"

Но мы все равно пойдем по неверному пути.

Давайте посмотрим на одну из ваших (реконструированных) индивидуальных stdout из results.

"stdout": "DEVNAME: /dev/sanstorage/node11-data102-2e385a327788d866e6c9ce9000b10399f\nUUID: 8c52d974-8584-4aa6-89b8-f1e1db016118\nTYPE: xfs"

Это строковое представление словаря yaml. Ansible имеет from_yaml фильтр. И мы можем использовать map filter, чтобы применить фильтр к каждому элемент в списке.

Приведенная ниже книга воспроизведения пытается воспроизвести ваши исходные данные, чтобы отобразить их за один раз.

---
- name: Parse a yaml dict in each element of a list
  hosts: localhost
  gather_facts: false

  vars:
    example_disks: 3

  tasks:

    - name: Faking your disk check supposed command
      shell: |-
        cat <<EOF
        DEVNAME: /dev/sanstorage/node{{ (item | string)*2 }}-data{{ (item | string)*3 }}-$(uuidgen)
        UUID: $(uuidgen)
        TYPE: xfs
        EOF
      loop: "{{ range(1, example_disks+1) }}"
      register: disk_check

    - name: Show the original data (use -v to trigger)
      debug:
        var: disk_check
        verbosity: 1

    - name: Display a list of dicts from the above result
      debug:
        msg: "{{ disk_check.results | map(attribute='stdout') | map('from_yaml') | list }}"

и дает (запустите с -v, чтобы показать промежуточную отладку):

PLAY [Parse a yaml dict in each element of a list] *************************************************************************************************************************************************************************************

TASK [Faking your disk check supposed command] *****************************************************************************************************************************************************************************************
changed: [localhost] => (item=1)
changed: [localhost] => (item=2)
changed: [localhost] => (item=3)

TASK [Show the original data (use -v to trigger)] **********************************************************************************************************************************************************************************************************
skipping: [localhost]

TASK [Display a list of dicts from the above result] ***********************************************************************************************************************************************************************************
ok: [localhost] => {
    "msg": [
        {
            "DEVNAME": "/dev/sanstorage/node11-data111-10e7a318-62af-46db-895e-5d94b0c2cf88",
            "TYPE": "xfs",
            "UUID": "5a87ae1c-c312-4325-88ac-b9cc1edfa69b"
        },
        {
            "DEVNAME": "/dev/sanstorage/node22-data222-18247d1d-87b2-4c7d-8d48-cd333d7530f9",
            "TYPE": "xfs",
            "UUID": "bc0d7f1a-16e4-4694-b3e2-904e69cc208d"
        },
        {
            "DEVNAME": "/dev/sanstorage/node33-data333-21bc7fde-645f-4cf2-9e18-72d004700085",
            "TYPE": "xfs",
            "UUID": "58985028-3eb1-4f34-90e9-f0e4c8257607"
        }
    ]
}

PLAY RECAP *****************************************************************************************************************************************************************************************************************************
localhost                  : ok=2    changed=1    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0 
02.04.2021
  • Благодаря тонну! Я действительно ценю многословие, проходящее через это. Я не забуду сохранить исходные команды в следующий раз. Удивительно, но не так много шагов для преобразования, как я ожидал. Для справки, disk_check исходит из команды оболочки, как вы и ожидали: ``` - name: check for filesystems shell: 'blkid {{ item }} -o export | sed -nr s/(.+)=(.+)/\1: \2/gp' loop: {{ Volume_device_path }} register: disk_check ignore_errors: true change_when: false ``` 02.04.2021
  • С удовольствием ;) Избегайте добавления кода в комментарии, особенно многострочные: они для этого не созданы (и очень изменчивы). Вместо этого вы можете отредактировать свой вопрос, и в этом случае было бы разумно добавить эту информацию. Ваше здоровье. 02.04.2021

  • 2

    Давайте упростим данные, например.

      first_list:
      - - a: 1
        - b: 1
      - - a: 2
        - b: 2
    

    Ожидаемый результат

      final_list:
      - a: 1
        b: 1
      - a: 2
        b: 2
    

    Задача ниже делает работу

        - set_fact:
            final_list: "{{ final_list|default([]) + [_dict|from_yaml] }}"
          loop: "{{ first_list }}"
          vars:
            _dict: |
              {% for i in item %}
              {{ (i|to_yaml)[1:-2] }}
              {% endfor %}
    

    Существуют и другие варианты форматирования элемента, например.

              {{ i.keys()|first }}: {{ i.values()|first }}
    

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

    shell> cat filter_plugins/list_filters.py
    def list2dict(l):
        out = []
        for i in l:
            item = {}
            for j in range(0, len(i)):
                item.update(i[j])
            out.append(item)
        return out
    
    
    class FilterModule(object):
        ''' List filters. '''
    
        def filters(self):
            return {
                'list2dict': list2dict,
            }
    

    Тогда простой фильтр ниже дает тот же результат

        - set_fact:
            final_list: "{{ first_list|list2dict }}"
    
    02.04.2021
    Новые материалы

    Кластеризация: более глубокий взгляд
    Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

    Как написать эффективное резюме
    Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

    Частный метод Python: улучшение инкапсуляции и безопасности
    Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

    Как я автоматизирую тестирование с помощью Jest
    Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

    Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
    В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..