在字典列表中打印键的特定值

问题描述 投票:0回答:2

我有这样的输入

ok: [localhost] => {
    "static_plugin_versions": [
        {
            "name": "ace-editor",
            "version": "1.1"
        },
        {
            "name": "analysis-core",
            "version": "1.95"
        },
        {
            "name": "ant",
            "version": "1.9"
        },
        {
            "name": "antisamy-markup-formatter",
            "version": "1.5"
        },
        {
            "name": "apache-httpcomponents-client-4-api",
            "version": "4.5.5-3.0"
        }
    ]
}

我的目标是通过指定一个特定的名称打印出version。在这种情况下,专门寻找versionanalysis-core

我试过的是以下内容

- debug:
    var: static_plugin_versions['analysis-core']['version']

- debug:
    var: static_plugin_versions['analysis-core'].version

- debug:
    var: static_plugin_versions[analysis-core.version]

唯一有效的是

- debug:
    var: static_plugin_versions[1].version

但这是不可行的,因为如果将更多条目添加到字典中,它将会中断。

任何迹象表明我在这里做错了什么。我正在寻找一种不依赖于循环的方式。

编辑

试过这个

- set_fact: 
    analysis_core_version: "{{ item.version }}"
  when: "'analysis-core' in item.name"
  with_items: "{{ static_plugin_versions }}"

- debug:
    var: analysis-core-version

但我得到:

TASK [copy : set_fact] *******************************************************************************************************************************************************************************************************************************************************************************************************
skipping: [localhost] => (item={u'version': u'1.1', u'name': u'ace-editor'})
ok: [localhost] => (item={u'version': u'1.95', u'name': u'analysis-core'})
skipping: [localhost] => (item={u'version': u'1.9', u'name': u'ant'})
skipping: [localhost] => (item={u'version': u'1.5', u'name': u'antisamy-markup-formatter'})
skipping: [localhost] => (item={u'version': u'4.5.5-3.0', u'name': u'apache-httpcomponents-client-4-api'})

TASK [copy : debug] **********************************************************************************************************************************************************************************************************************************************************************************************************
ok: [localhost] => {
    "analysis-core-version": "VARIABLE IS NOT DEFINED!"
}
ansible
2个回答
1
投票

最简单的方法是使用selectattr过滤器,它允许您将过滤器应用于对象列表。例如,如果我有这个剧本:

---
- hosts: localhost
  gather_facts: false
  vars:
    "static_plugin_versions": [
      {
        "name": "ace-editor",
        "version": "1.1"
      },
      {
        "name": "analysis-core",
        "version": "1.95"
      },
      {
        "name": "ant",
        "version": "1.9"
      },
      {
        "name": "antisamy-markup-formatter",
        "version": "1.5"
      },
      {
        "name": "apache-httpcomponents-client-4-api",
        "version": "4.5.5-3.0"
      }
    ]
  tasks:
    - debug:
        msg: "version of {{ item }} is {{ (static_plugin_versions|selectattr('name', 'eq', item)|first).version }}"
      loop:
        - ace-editor

输出将是:

TASK [debug] **********************************************************************************************************************************************************************************
ok: [localhost] => (item=ace-editor) => {
    "msg": "version of ace-editor is 1.1"
}

或者,使用您的示例:

- set_fact: 
    analysis_core_version: "{{ (static_plugin_versions|selectattr('name', 'eq', 'analysis-core')|first).version }}"

- debug:
    var: analysis-core-version

哪个产生:

ok: [localhost] => {
    "analysis_core_version": "1.95"
}

如有必要,json_query过滤器允许更复杂的查询。


0
投票

Solution 1 (not optimized)

正如Illias评论所建议的那样,您可以使用循环来遍历列表中的其他每个元素,匹配其name值并在满足条件时打印其version

- name: print version of analysis-core
  debug:
    msg: "{{ item.version }}"
  when: item.name == 'analysis-core'
  loop: "{{ static_plugin_versions }}"

同时,只要没有匹配,这将转到其他每个元素并跳过任务。如果你有数百个插件,这将很快在你的ansible执行日志中变得不可读。

Solution 2 (my preferred)

查询您的数据结构以获得您所需的确切内容。你的朋友在这里是json_query filter(如果你想进一步,你应该阅读jmespath doc)。对于你的特定例子

- name: print version of analysis-core
  debug:
    msg: >-
      {{ (static_plugin_versions | json_query("[?name == 'analysis-core'].version")).0 }}

笔记:

  1. 我推断您的插件名称列表中的唯一名称。因此,查询特定的插件名称会返回单个元素,我可以打印列表中的第一个作为预期结果。
  2. 单引号和双引号的顺序在上面的例子中很重要(参见jmespath specification:如果你切换它们,你会得到一个空字符串结果。
  3. 我在我的例子中使用了一个yaml折叠块,所以我没有逃避双引号(因为我是一个非常懒的B @ sT @ rD:D),但你可以使用普通的字符串并转义双引号如果你希望。
© www.soinside.com 2019 - 2024. All rights reserved.