Jinja2过滤列表使用字符串包含test

时间:2016-02-09 00:16:51

标签: jinja2 ansible ansible-2.x

当元素包含一个字符串时,我正试图在Jinja2中过滤ansible中的列表,但是Jinja文档似乎不够清晰,我无法弄明白。

这是我到目前为止所做的:

- name: run script
  command: /usr/tmp/run_script.py
  register: script_results

- name: display run info
  debug:
    var: "{{script_results.stdout_lines | select(\"'running script' in script_results.stdout_lines\") }}"

但我得到的只是错误:

"<generator object _select_or_reject at 0x13851e0>": "VARIABLE IS NOT DEFINED!"

例如,如果stdout_lines包含["apples","running script one","oranges","running script two"],我想打印

running script one
running script two

他们有documentation for selectdocumentation for built-in-tests,但他们没有显示“in”测试,我不知道它们在这个ansible变量的上下文中是如何工作的。

我试着像这样解决它:

- name: display run info
  debug:
    var: item
  with_items: "{{script_results.stdout_lines}}"
  when: "'running script' in item"

但是对于没有通过测试的每一行显示“跳过”...有点击败目的!

4 个答案:

答案 0 :(得分:14)

select过滤器需要另一个过滤器。就像在文档odd中一样,它只返回列表中的奇数元素。要与select合并的过滤器为equalto

现在就是这样。 Ansible捆绑了一个非常旧版本的Jinja2,它只是不包含equalto过滤器。是的,除非你想过滤奇数元素,否则它会变得无用。 (历史上没有人想要......)

此外,我还无法在Ansible 2中使自定义过滤器插件工作。所以你几乎不得不一起破解丑陋的东西。

helloV已经显示了一个选项。这是另一个想法:

- name: run script
  shell: /usr/tmp/run_script.py | grep "running script"
  register: script_results

更新

我最近发现你可以使用match(不是标准的Jinja2过滤器,但是由Ansible添加)和select。这是eualto过滤器的一个很好的替代品,你可以使用正则表达式。这应该有效:

{{ script_results.stdout_lines | select("match", ".*running script.*") }}

答案 1 :(得分:4)

我知道可能有多种方法可以做到这一点。这对你有用吗?

  - debug: var={{item}}
    when: item.find('running script') > -1
    with_items: script_results.stdout_lines

答案 2 :(得分:0)

我最终编写了一个python脚本来完成它,因为我无法获得ansible或者古代jinja2来制作剪辑。

Ansible任务:

- name: gather run info
  command: "{{role_path}}/files/print_results.py {{script_results.stdout_lines}}"
  register: script_print_results
  delegate_to: 127.0.0.1
  run_once: true

- name: display run info
  debug:
    var: script_print_results.stdout_lines
  delegate_to: 127.0.0.1
  run_once: true

Python脚本:

for result_line in sys.argv[1:]:
    if "running script:" in result_line:
        print result_line[1:-1]

答案 3 :(得分:0)

您可以使用set_fact构建新列表,并打印新列表的元素。

- hosts: localhost
  gather_facts: false
  vars:
    script_stdout_lines:
      - apples
      - running script one
      - oranges
      - running script two
  tasks:
    - set_fact:
        new_list: "{{ new_list | default([]) + [item] }}"
      with_items: "{{ script_stdout_lines }}"
      when: '"running script" in item'
    - debug: var=new_list

结果:

TASK [set_fact] *********************************************************************************************************************
skipping: [localhost] => (item=apples) 
ok: [localhost] => (item=running script one)
skipping: [localhost] => (item=oranges) 
ok: [localhost] => (item=running script two)

TASK [debug] ************************************************************************************************************************
ok: [localhost] => {
    "new_list": [
        "running script one",
        "running script two"
    ]
}

它在skipping操作期间打印set_fact,但最后它提供了一个仅包含匹配项目的新列表。