在 jinja2 (ansible) 中为列表的元素添加引号

Add quotes to elemens of the list in jinja2 (ansible)

我在模板中有非常简单的一行:

ip={{ip|join(', ')}}

我有 ip 列表:

ip:
 - 1.1.1.1
 - 2.2.2.2
 - 3.3.3.3

但应用程序需要带引号的 IP (ip='1.1.1.1', '2.2.2.2')。

我可以这样做:

ip:
 - "'1.1.1.1'"
 - "'2.2.2.2'"
 - "'3.3.3.3'"

但是很丑。在 ansible 中为列表的每个元素添加引号有什么好的方法吗?

谢谢!

尝试:

- hosts: localhost
  tags: s20
  gather_facts: no
  vars:
    ip:
      - 1.1.1.1
      - 2.2.2.2
      - 3.3.3.3
    joined_ip: "'{{ \"', '\".join(ip)}}'"
  tasks:
  - debug: msg="(ip={{joined_ip}})"

PS:ansible 支持 {{}} 中的一些 python 代码执行,这就是我在这里滥用的内容。

这会起作用:

ip={{ '\"' + ip|join('\", \"') + '\"' }}

自定义过滤器插件也可以使用。在 ansible.cfg 取消注释 filter_plugins 并给它一个路径,我们把这个

def wrap(list):
    return [ '"' + x + '"' for x in list]

class FilterModule(object):
    def filters(self):
        return {
            'wrap': wrap
        }

在名为 core.py 的文件中。 Like this。然后你可以简单地使用

ip|wrap|join(', ')

它应该生成逗号分隔的列表,每个 ip 都用引号引起来。

我开发了一个自定义 wrap 过滤器

def wrap(value, wrapper = '"'):
  return wrapper + value + wrapper

class FilterModule(object):
  def filters(self):
    return {
      'wrap': wrap
    }

如您所见,wrapper 是可自定义的,默认为 "

你可以这样使用

ip={{ ip | map('wrap') | join(', ') }}

免责声明:我是一个 python 和 ansible 新手

其实有一个很简单的方法可以实现:

{{ mylist | map('quote') | join(', ') }}

过滤器 map 遍历每个项目并让 quote 处理它。之后,您可以轻松地 join 将它们组合在一起。

注意 这类似于 Kashyap 的回答,但我需要一个稍微不同的版本:使用它来双引号 bash 数组中的每个项目),例如。结果应该是:

SOME_LIST=( "Johnny" "Joey" "Dee Dee" "Tommy" )

projects/ansible/expand_list.yml

---
- hosts: localhost
  connection: local

  vars:
    some_list:
      - Johnny
      - Joey
      - Dee Dee
      - Tommy

  tasks:
    - name: "Expand the ramones band members list."
      template:
        src: "templates/expand_list.conf.j2"
        dest: "/var/tmp/ramones.conf"

projects/ansible/templates/expand_list.conf.j2

SOME_LIST=( "{{ '" "'.join(some_list) }}" )

以下对我有用

('{{ iplist | join('\',\'') }}')

例如:

Inventory

[ips]
1.1.1.1
2.2.2.2
3.3.3.3

#cat temp.sh.j2 

 "ips": (ip='{{ groups['zoo'] | join('\',\'') }}') 

result:

#cat temp.sh

 "ips": (ip='1.1.1.1','2.2.2.2','3.3.3.3')

希望对大家有所帮助。

我发现使用现有 Ansible 过滤器执行此操作的最简单方法是使用 regex_replace

{{ ip | map("regex_replace","(.+)","\'\1\'") | join(',')}}

您可以使用 regex_replace、f.e。在 j2 模板文件中:

(ip={{ip | map('regex_replace', '(.*)', "'\1'") | join(',')}})

如果您在剧本中这样做,请不要忘记对双引号进行转义。这是一个完整的例子:

- hosts: localhost
  gather_facts: no
  vars:
    ip:
    - 1.1.1.1
    - 2.2.2.2
    - 3.3.3.3
    ip_result: "{{ip | map('regex_replace', '(.*)', \"'\1'\") | join(',')}}"
  tasks:
  - debug: msg="(ip={{ip_result}})"
  - copy: content="(ip={{ip_result}})" dest=./ip_result.txt

ip_result.txt的内容:

$ cat ip_result.txt
(ip='1.1.1.1','2.2.2.2','3.3.3.3')

如本博客所述:https://medium.com/opsops/how-enquote-list-elements-faab833e25fe

使用to_json过滤器。这将 双引号 列表中的每个字符串:

list_of_string | map("to_json")

“quote”过滤器的问题在于它不会引用从 bash 角度不需要引用的元素(字符串中没有 space)。但是对于 windows 命令,有时无论如何都必须引用字符串。