使用过滤器操作数据

过滤器允许您将 JSON 数据转换为 YAML 数据、拆分 URL 以提取主机名、获取字符串的 SHA1 哈希值、添加或乘以整数等等。您可以使用此处记录的特定于 Ansible 的过滤器来操作您的数据,或者使用与 Jinja2 一起提供的任何标准过滤器 - 请参阅官方 Jinja2 模板文档中 内置过滤器 的列表。您还可以使用 Python 方法 来转换数据。您可以 创建自定义 Ansible 过滤器作为插件,尽管我们通常欢迎将新过滤器添加到 ansible-core 存储库中,以便每个人都可以使用它们。

由于模板化是在 Ansible 控制节点上进行的,而不是在目标主机上进行的,因此过滤器在控制节点上执行并在本地转换数据。

处理未定义的变量

过滤器可以通过提供默认值或使某些变量可选来帮助您管理缺失或未定义的变量。如果您配置 Ansible 忽略大多数未定义的变量,则可以使用 mandatory 过滤器将某些变量标记为需要值。

提供默认值

您可以使用 Jinja2 的“default”过滤器直接在模板中为变量提供默认值。这通常比在未定义变量时失败更好的方法

{{ some_variable | default(5) }}

在上面的示例中,如果变量“some_variable”未定义,Ansible 将使用默认值 5,而不是引发“未定义变量”错误并失败。如果您在角色中工作,也可以添加角色默认值来定义角色中变量的默认值。要了解有关角色默认值的更多信息,请参阅 角色目录结构

从版本 2.8 开始,尝试访问 Jinja 中 Undefined 值的属性将返回另一个 Undefined 值,而不是立即抛出错误。这意味着您现在可以简单地在嵌套数据结构中使用带有值的默认值(换句话说,{{ foo.bar.baz | default('DEFAULT') }}),当您不知道中间值是否已定义时。

如果要在变量计算为 false 或空字符串时使用默认值,则必须将第二个参数设置为 true

{{ lookup('env', 'MY_USER') | default('admin', true) }}

使变量可选

默认情况下,Ansible 要求模板表达式中的所有变量都有值。但是,您可以使特定模块变量可选。例如,您可能希望对某些项目使用系统默认值,并控制其他项目的 value。要使模块变量可选,请将默认值设置为特殊变量 omit

- name: Touch files with an optional mode
  ansible.builtin.file:
    dest: "{{ item.path }}"
    state: touch
    mode: "{{ item.mode | default(omit) }}"
  loop:
    - path: /tmp/foo
    - path: /tmp/bar
    - path: /tmp/baz
      mode: "0444"

在此示例中,文件 /tmp/foo/tmp/bar 的默认模式由系统的 umask 决定。Ansible 不会为 mode 发送值。只有第三个文件 /tmp/baz 会收到 mode=0444 选项。

注意

如果您在 default(omit) 过滤器之后“链接”其他过滤器,您应该改为执行类似以下操作:"{{ foo | default(None) | some_filter or omit }}"。在此示例中,默认 None(Python 空)值将导致后面的过滤器失败,这将触发逻辑的 or omit 部分。但是,以这种方式使用 omit 对您正在链接的后面过滤器非常具体,因此如果您这样做,请准备好进行一些尝试和错误。

定义必填值

如果您配置 Ansible 忽略未定义的变量,您可能希望将某些值定义为必填的。默认情况下,如果剧本或命令中的变量未定义,Ansible 将失败。您可以通过将 DEFAULT_UNDEFINED_VAR_BEHAVIOR 设置为 false 来配置 Ansible 以允许未定义的变量。在这种情况下,您可能希望要求定义某些变量。您可以使用以下方法来实现:

{{ variable | mandatory }}

变量值将按原样使用,但如果变量未定义,模板评估将引发错误。

要求覆盖变量的一种便捷方法是使用 undef() 函数为其赋予未定义的值。

galaxy_url: "https://galaxy.ansible.com"
galaxy_api_key: "{{ undef(hint='You must specify your Galaxy API key') }}"

为 true/false/null 定义不同的值(三元运算符)

您可以创建一个测试,然后定义一个值在测试返回 true 时使用,另一个值在测试返回 false 时使用(版本 1.9 中的新增功能)

{{ (status == 'needs_restart') | ternary('restart', 'continue') }}

此外,您可以在 true 上定义一个值,在 false 上定义一个值,在 null 上定义第三个值(版本 2.8 中的新增功能)

{{ enabled | ternary('no shutdown', 'shutdown', omit) }}

管理数据类型

您可能需要了解、更改或设置变量的数据类型。例如,注册的变量可能包含字典,而您的下一个任务需要列表,或者用户 提示 可能返回字符串,而您的剧本需要布尔值。使用 ansible.builtin.type_debugansible.builtin.dict2itemsansible.builtin.items2dict 过滤器来管理数据类型。您也可以使用数据类型本身将值转换为特定数据类型。

发现数据类型

版本 2.3 中的新增功能。

如果您不确定变量的底层 Python 类型,可以使用 ansible.builtin.type_debug 过滤器来显示它。这在您需要特定类型变量的调试时很有用。

{{ myvar | type_debug }}

您应该注意,虽然这似乎是一个用于检查变量中是否具有正确数据类型的有用过滤器,但您通常应该优先使用 类型测试,这将允许您测试特定数据类型。

将字符串转换为列表

使用 ansible.builtin.split 过滤器将字符/字符串分隔的字符串转换为适合 循环 的项目列表。例如,如果您想通过逗号分割字符串变量 fruits,您可以使用

{{ fruits | split(',') }}

字符串数据(在应用 ansible.builtin.split 过滤器之前)

fruits: apple,banana,orange

列表数据(在应用 ansible.builtin.split 过滤器之后)

- apple
- banana
- orange

将字典转换为列表

版本 2.6 中的新功能。

使用 ansible.builtin.dict2items 过滤器将字典转换为适合 循环 的项目列表

{{ dict | dict2items }}

字典数据(在应用 ansible.builtin.dict2items 过滤器之前)

tags:
  Application: payment
  Environment: dev

列表数据(在应用 ansible.builtin.dict2items 过滤器之后)

- key: Application
  value: payment
- key: Environment
  value: dev

版本 2.8 中的新功能。

ansible.builtin.dict2items 过滤器是 ansible.builtin.items2dict 过滤器的反向。

如果您想配置键的名称,ansible.builtin.dict2items 过滤器接受 2 个关键字参数。传递 key_namevalue_name 参数来配置列表输出中键的名称

{{ files | dict2items(key_name='file', value_name='path') }}

字典数据(在应用 ansible.builtin.dict2items 过滤器之前)

files:
  users: /etc/passwd
  groups: /etc/group

列表数据(在应用 ansible.builtin.dict2items 过滤器之后)

- file: users
  path: /etc/passwd
- file: groups
  path: /etc/group

将列表转换为字典

版本 2.7 中的新功能。

使用 ansible.builtin.items2dict 过滤器将列表转换为字典,将内容映射到 key: value

{{ tags | items2dict }}

列表数据(在应用 ansible.builtin.items2dict 过滤器之前)

tags:
  - key: Application
    value: payment
  - key: Environment
    value: dev

字典数据(在应用 ansible.builtin.items2dict 过滤器之后)

Application: payment
Environment: dev

ansible.builtin.items2dict 过滤器是 ansible.builtin.dict2items 过滤器的反向。

并非所有列表都使用 key 来指定键,并使用 value 来指定值。例如

fruits:
  - fruit: apple
    color: red
  - fruit: pear
    color: yellow
  - fruit: grapefruit
    color: yellow

在此示例中,您必须传递 key_namevalue_name 参数来配置转换。例如

{{ fruits | items2dict(key_name='fruit', value_name='color') }}

如果您不传递这些参数,或者没有为您的列表传递正确的值,您将看到 KeyError: keyKeyError: my_typo

强制数据类型

您可以将值强制转换为特定类型。例如,如果您期望来自 vars_prompt 的输入“True”,并且您希望 Ansible 将其识别为布尔值而不是字符串

- ansible.builtin.debug:
     msg: test
  when: some_string_value | bool

如果您想对事实进行数学比较,并且您希望 Ansible 将其识别为整数而不是字符串

- shell: echo "only on Red Hat 6, derivatives, and later"
  when: ansible_facts['os_family'] == "RedHat" and ansible_facts['lsb']['major_release'] | int >= 6

版本 1.6 中的新功能。

格式化数据:YAML 和 JSON

您可以将模板中的数据结构从 JSON 或 YAML 格式切换到或从 JSON 或 YAML 格式切换到,并提供格式化、缩进和加载数据的选项。基本过滤器偶尔用于调试

{{ some_variable | to_json }}
{{ some_variable | to_yaml }}

有关这些过滤器的文档,请参见 ansible.builtin.to_jsonansible.builtin.to_yaml

对于人类可读的输出,您可以使用

{{ some_variable | to_nice_json }}
{{ some_variable | to_nice_yaml }}

有关这些过滤器的文档,请参见 ansible.builtin.to_nice_jsonansible.builtin.to_nice_yaml

您可以更改两种格式的缩进

{{ some_variable | to_nice_json(indent=2) }}
{{ some_variable | to_nice_yaml(indent=8) }}

ansible.builtin.to_yamlansible.builtin.to_nice_yaml 过滤器使用 PyYAML 库,该库具有默认的 80 个符号字符串长度限制。这会导致在第 80 个符号之后出现意外的换行符(如果第 80 个符号之后有空格)。为了避免这种行为并生成长行,请使用 width 选项。您必须使用硬编码的数字来定义宽度,而不是像 float("inf") 这样的构造,因为过滤器不支持代理 Python 函数。例如

{{ some_variable | to_yaml(indent=8, width=1337) }}
{{ some_variable | to_nice_yaml(indent=8, width=1337) }}

过滤器支持传递其他 YAML 参数。有关完整列表,请参见 PyYAML 文档 中的 dump()

如果您正在读取一些已格式化的数据

{{ some_variable | from_json }}
{{ some_variable | from_yaml }}

例如

tasks:
  - name: Register JSON output as a variable
    ansible.builtin.shell: cat /some/path/to/file.json
    register: result

  - name: Set a variable
    ansible.builtin.set_fact:
      myvar: "{{ result.stdout | from_json }}"

过滤器 to_json 和 Unicode 支持

默认情况下,ansible.builtin.to_jsonansible.builtin.to_nice_json 将接收到的数据转换为 ASCII,因此

{{ 'München'| to_json }}

将返回

'M\u00fcnchen'

要保留 Unicode 字符,请将参数 ensure_ascii=False 传递给过滤器

{{ 'München'| to_json(ensure_ascii=False) }}

'München'

版本 2.7 中的新功能。

要解析多文档 YAML 字符串,提供了 ansible.builtin.from_yaml_all 过滤器。 ansible.builtin.from_yaml_all 过滤器将返回解析的 YAML 文档的生成器。

例如

tasks:
  - name: Register a file content as a variable
    ansible.builtin.shell: cat /some/path/to/multidoc-file.yaml
    register: result

  - name: Print the transformed variable
    ansible.builtin.debug:
      msg: '{{ item }}'
    loop: '{{ result.stdout | from_yaml_all | list }}'

组合和选择数据

您可以组合来自多个源和类型的,并从大型数据结构中选择值,从而使您对复杂数据进行精确控制。

组合来自多个列表的项目:zip 和 zip_longest

版本 2.3 中的新增功能。

要获得一个组合了其他列表元素的列表,请使用 ansible.builtin.zip

- name: Give me list combo of two lists
  ansible.builtin.debug:
    msg: "{{ [1,2,3,4,5,6] | zip(['a','b','c','d','e','f']) | list }}"

# => [[1, "a"], [2, "b"], [3, "c"], [4, "d"], [5, "e"], [6, "f"]]

- name: Give me the shortest combo of two lists
  ansible.builtin.debug:
    msg: "{{ [1,2,3] | zip(['a','b','c','d','e','f']) | list }}"

# => [[1, "a"], [2, "b"], [3, "c"]]

要始终穷尽所有列表,请使用 ansible.builtin.zip_longest

- name: Give me the longest combo of three lists, fill with X
  ansible.builtin.debug:
    msg: "{{ [1,2,3] | zip_longest(['a','b','c','d','e','f'], [21, 22, 23], fillvalue='X') | list }}"

# => [[1, "a", 21], [2, "b", 22], [3, "c", 23], ["X", "d", "X"], ["X", "e", "X"], ["X", "f", "X"]]

与上面提到的 ansible.builtin.items2dict 过滤器的输出类似,这些过滤器可用于构建 dict

{{ dict(keys_list | zip(values_list)) }}

列表数据(在应用 ansible.builtin.zip 过滤器之前)

keys_list:
  - one
  - two
values_list:
  - apple
  - orange

字典数据(在应用 ansible.builtin.zip 过滤器之后)

one: apple
two: orange

组合对象和子元素

版本 2.7 中的新功能。

ansible.builtin.subelements 过滤器生成对象与其子元素值的乘积,类似于 ansible.builtin.subelements 查找。这使您能够指定在模板中使用的单个子元素。例如,此表达式

{{ users | subelements('groups', skip_missing=True) }}

应用 ansible.builtin.subelements 过滤器之前的 数据

users:
- name: alice
  authorized:
  - /tmp/alice/onekey.pub
  - /tmp/alice/twokey.pub
  groups:
  - wheel
  - docker
- name: bob
  authorized:
  - /tmp/bob/id_rsa.pub
  groups:
  - docker

应用 ansible.builtin.subelements 过滤器之后的数据

-
  - name: alice
    groups:
    - wheel
    - docker
    authorized:
    - /tmp/alice/onekey.pub
    - /tmp/alice/twokey.pub
  - wheel
-
  - name: alice
    groups:
    - wheel
    - docker
    authorized:
    - /tmp/alice/onekey.pub
    - /tmp/alice/twokey.pub
  - docker
-
  - name: bob
    authorized:
    - /tmp/bob/id_rsa.pub
    groups:
    - docker
  - docker

您可以使用转换后的数据与 loop 来迭代多个对象中的相同子元素

- name: Set authorized ssh key, extracting just that data from 'users'
  ansible.posix.authorized_key:
    user: "{{ item.0.name }}"
    key: "{{ lookup('file', item.1) }}"
  loop: "{{ users | subelements('authorized') }}"

组合哈希/字典

新增于 2.0 版本。

ansible.builtin.combine 过滤器允许合并哈希。例如,以下示例将覆盖一个哈希中的键

{{ {'a':1, 'b':2} | combine({'b':3}) }}

最终的哈希将是

{'a':1, 'b':3}

该过滤器还可以接受多个参数来合并

{{ a | combine(b, c, d) }}
{{ [a, b, c, d] | combine }}

在这种情况下,d 中的键将覆盖 c 中的键,而 c 中的键将覆盖 b 中的键,依此类推。

该过滤器还接受两个可选参数:recursivelist_merge

recursive

是一个布尔值,默认为 False。是否 ansible.builtin.combine 递归地合并嵌套的哈希。注意:它不依赖于 ansible.cfg 中的 hash_behaviour 设置的值。

list_merge

是一个字符串,其可能的值为 replace(默认)、keepappendprependappend_rpprepend_rp。它修改了 ansible.builtin.combine 在要合并的哈希包含数组/列表时的行为。

default:
  a:
    x: default
    y: default
  b: default
  c: default
patch:
  a:
    y: patch
    z: patch
  b: patch

如果 recursive=False(默认),嵌套的哈希不会合并

{{ default | combine(patch) }}

这将导致

a:
  y: patch
  z: patch
b: patch
c: default

如果 recursive=True,递归到嵌套的哈希中并合并它们的键

{{ default | combine(patch, recursive=True) }}

这将导致

a:
  x: default
  y: patch
  z: patch
b: patch
c: default

如果 list_merge='replace'(默认),右侧哈希中的数组将“替换”左侧哈希中的数组

default:
  a:
    - default
patch:
  a:
    - patch
{{ default | combine(patch) }}

这将导致

a:
  - patch

如果 list_merge='keep',左侧哈希中的数组将被保留

{{ default | combine(patch, list_merge='keep') }}

这将导致

a:
  - default

如果 list_merge='append',右侧哈希中的数组将被追加到左侧哈希中的数组

{{ default | combine(patch, list_merge='append') }}

这将导致

a:
  - default
  - patch

如果 list_merge='prepend',右侧哈希中的数组将被预置到左侧哈希中的数组

{{ default | combine(patch, list_merge='prepend') }}

这将导致

a:
  - patch
  - default

如果 list_merge='append_rp',右侧哈希中的数组将被追加到左侧哈希中的数组。左侧哈希中的数组中也出现在右侧哈希的相应数组中的元素将被删除(“rp”代表“删除存在”)。未出现在两个哈希中的重复元素将被保留

default:
  a:
    - 1
    - 1
    - 2
    - 3
patch:
  a:
    - 3
    - 4
    - 5
    - 5
{{ default | combine(patch, list_merge='append_rp') }}

这将导致

a:
  - 1
  - 1
  - 2
  - 3
  - 4
  - 5
  - 5

如果 list_merge='prepend_rp',行为类似于 append_rp,但右侧哈希中的数组元素将被预置

{{ default | combine(patch, list_merge='prepend_rp') }}

这将导致

a:
  - 3
  - 4
  - 5
  - 5
  - 1
  - 1
  - 2

recursivelist_merge 可以一起使用

default:
  a:
    a':
      x: default_value
      y: default_value
      list:
        - default_value
  b:
    - 1
    - 1
    - 2
    - 3
patch:
  a:
    a':
      y: patch_value
      z: patch_value
      list:
        - patch_value
  b:
    - 3
    - 4
    - 4
    - key: value
{{ default | combine(patch, recursive=True, list_merge='append_rp') }}

这将导致

a:
  a':
    x: default_value
    y: patch_value
    z: patch_value
    list:
      - default_value
      - patch_value
b:
  - 1
  - 1
  - 2
  - 3
  - 4
  - 4
  - key: value

从数组或哈希表中选择值

新增于 2.1 版本。

extract 过滤器用于从容器(哈希或数组)中将索引列表映射到值列表

{{ [0,2] | map('extract', ['x','y','z']) | list }}
{{ ['x','y'] | map('extract', {'x': 42, 'y': 31}) | list }}

上述表达式的结果将是

['x', 'z']
[42, 31]

该过滤器可以接受另一个参数

{{ groups['x'] | map('extract', hostvars, 'ec2_ip_address') | list }}

这将在“x”组中获取主机列表,在 hostvars 中查找它们,然后查找结果的 ec2_ip_address。最终结果是“x”组中主机的 IP 地址列表。

该过滤器的第三个参数也可以是列表,用于在容器中进行递归查找

{{ ['a'] | map('extract', b, ['x','y']) | list }}

这将返回一个包含 b[‘a’][‘x’][‘y’] 值的列表。

组合列表

这组过滤器返回一个组合列表的列表。

permutations

要获取列表的排列

- name: Give me the largest permutations (order matters)
  ansible.builtin.debug:
    msg: "{{ [1,2,3,4,5] | ansible.builtin.permutations | list }}"

- name: Give me permutations of sets of three
  ansible.builtin.debug:
    msg: "{{ [1,2,3,4,5] | ansible.builtin.permutations(3) | list }}"

combinations

组合总是需要一个集合大小

- name: Give me combinations for sets of two
  ansible.builtin.debug:
    msg: "{{ [1,2,3,4,5] | ansible.builtin.combinations(2) | list }}"

另请参阅 zip_filter

products

product 过滤器返回输入可迭代对象的 笛卡尔积。这大致等同于生成器表达式中的嵌套 for 循环。

例如

- name: Generate multiple hostnames
  ansible.builtin.debug:
    msg: "{{ ['foo', 'bar'] | product(['com']) | map('join', '.') | join(',') }}"

这将导致

{ "msg": "foo.com,bar.com" }

选择 JSON 数据:JSON 查询

要从 JSON 格式的复杂数据结构(例如 Ansible 事实)中选择单个元素或数据子集,请使用 community.general.json_query 过滤器。community.general.json_query 过滤器允许您查询复杂的 JSON 结构并使用循环结构迭代它。

注意

此过滤器已迁移到 community.general 集合。请按照安装说明安装该集合。

注意

在使用此过滤器之前,您必须在 Ansible 控制节点上手动安装 jmespath 依赖项。此过滤器基于 jmespath,您可以使用相同的语法。有关示例,请参阅 jmespath 示例

请考虑以下数据结构

{
    "domain": {
        "cluster": [
            {
                "name": "cluster1"
            },
            {
                "name": "cluster2"
            }
        ],
        "server": [
            {
                "name": "server11",
                "cluster": "cluster1",
                "port": "8080"
            },
            {
                "name": "server12",
                "cluster": "cluster1",
                "port": "8090"
            },
            {
                "name": "server21",
                "cluster": "cluster2",
                "port": "9080"
            },
            {
                "name": "server22",
                "cluster": "cluster2",
                "port": "9090"
            }
        ],
        "library": [
            {
                "name": "lib1",
                "target": "cluster1"
            },
            {
                "name": "lib2",
                "target": "cluster2"
            }
        ]
    }
}

要从该结构中提取所有集群,可以使用以下查询

- name: Display all cluster names
  ansible.builtin.debug:
    var: item
  loop: "{{ domain_definition | community.general.json_query('domain.cluster[*].name') }}"

要提取所有服务器名称

- name: Display all server names
  ansible.builtin.debug:
    var: item
  loop: "{{ domain_definition | community.general.json_query('domain.server[*].name') }}"

要从 cluster1 中提取端口

- name: Display all ports from cluster1
  ansible.builtin.debug:
    var: item
  loop: "{{ domain_definition | community.general.json_query(server_name_cluster1_query) }}"
  vars:
    server_name_cluster1_query: "domain.server[?cluster=='cluster1'].port"

注意

您可以使用变量使查询更具可读性。

要以逗号分隔的字符串形式打印 cluster1 中的端口

- name: Display all ports from cluster1 as a string
  ansible.builtin.debug:
    msg: "{{ domain_definition | community.general.json_query('domain.server[?cluster==`cluster1`].port') | join(', ') }}"

注意

在上面的示例中,使用反引号引用字面量可以避免转义引号并保持可读性。

您可以使用 YAML 单引号转义

- name: Display all ports from cluster1
  ansible.builtin.debug:
    var: item
  loop: "{{ domain_definition | community.general.json_query('domain.server[?cluster==''cluster1''].port') }}"

注意

在 YAML 中,单引号内的单引号转义是通过将单引号加倍来完成的。

要获取一个包含所有集群端口和名称的哈希映射

- name: Display all server ports and names from cluster1
  ansible.builtin.debug:
    var: item
  loop: "{{ domain_definition | community.general.json_query(server_name_cluster1_query) }}"
  vars:
    server_name_cluster1_query: "domain.server[?cluster=='cluster1'].{name: name, port: port}"

要从名称以“server1”开头的所有集群中提取端口

- name: Display ports from all clusters with the name starting with 'server1'
  ansible.builtin.debug:
    msg: "{{ domain_definition | to_json | from_json | community.general.json_query(server_name_query) }}"
  vars:
    server_name_query: "domain.server[?starts_with(name,'server1')].port"

要从名称包含“server1”的所有集群中提取端口

- name: Display ports from all clusters with the name containing 'server1'
  ansible.builtin.debug:
    msg: "{{ domain_definition | to_json | from_json | community.general.json_query(server_name_query) }}"
  vars:
    server_name_query: "domain.server[?contains(name,'server1')].port"

注意

在使用 starts_withcontains 时,您必须使用 `` to_json | from_json `` 过滤器来正确解析数据结构。

随机化数据

当您需要随机生成的值时,请使用以下过滤器之一。

随机 MAC 地址

版本 2.6 中的新功能。

此过滤器可用于从字符串前缀生成随机 MAC 地址。

注意

此过滤器已迁移到 community.general 集合。请按照安装说明安装该集合。

要从以“52:54:00”开头的字符串前缀获取随机 MAC 地址

"{{ '52:54:00' | community.general.random_mac }}"
# => '52:54:00:ef:1c:03'

请注意,如果前缀字符串有任何错误,该过滤器将发出错误。

新增于 2.9 版本。

从 Ansible 版本 2.9 开始,您还可以从种子初始化随机数生成器以创建随机但幂等的 MAC 地址

"{{ '52:54:00' | community.general.random_mac(seed=inventory_hostname) }}"

随机项目或数字

Ansible 中的 ansible.builtin.random 过滤器是对默认 Jinja2 随机过滤器的扩展,可用于从一系列项中返回随机项,或根据范围生成随机数。

从列表中获取随机项

"{{ ['a','b','c'] | random }}"
# => 'c'

获取 0(包含)到指定整数(不包含)之间的随机数

"{{ 60 | random }} * * * * root /script/from/cron"
# => '21 * * * * root /script/from/cron'

获取 0 到 100 之间的随机数,但步长为 10

{{ 101 | random(step=10) }}
# => 70

获取 1 到 100 之间的随机数,但步长为 10

{{ 101 | random(1, 10) }}
# => 31
{{ 101 | random(start=1, step=10) }}
# => 51

您可以从种子初始化随机数生成器,以创建随机但幂等的数字

"{{ 60 | random(seed=inventory_hostname) }} * * * * root /script/from/cron"

洗牌列表

The ansible.builtin.shuffle 过滤器随机化现有列表,在每次调用时提供不同的顺序。

从现有列表中获取随机列表

{{ ['a','b','c'] | shuffle }}
# => ['c','a','b']
{{ ['a','b','c'] | shuffle }}
# => ['b','c','a']

您可以从种子初始化洗牌生成器,以生成随机但幂等的顺序

{{ ['a','b','c'] | shuffle(seed=inventory_hostname) }}
# => ['b','a','c']

shuffle 过滤器在可能的情况下返回列表。如果您将其与非“可列表”项一起使用,则过滤器将不执行任何操作。

管理列表变量

您可以搜索列表中的最小值或最大值,或展平多级列表。

从数字列表中获取最小值

{{ list1 | min }}

版本 2.11 中的新增功能。

从对象列表中获取最小值

{{ [{'val': 1}, {'val': 2}] | min(attribute='val') }}

从数字列表中获取最大值

{{ [3, 4, 2] | max }}

版本 2.11 中的新增功能。

从对象列表中获取最大值

{{ [{'val': 1}, {'val': 2}] | max(attribute='val') }}

版本 2.5 中的新增功能。

展平列表(与 flatten 查找相同)

{{ [3, [4, 2] ] | flatten }}
# => [3, 4, 2]

仅展平列表的第一级(类似于 items 查找)

{{ [3, [4, [2]] ] | flatten(levels=1) }}
# => [3, 4, [2]]

版本 2.11 中的新增功能。

在列表中保留空值,默认情况下,展平会删除它们。

{{ [3, None, [4, [2]] ] | flatten(levels=1, skip_nulls=False) }}
# => [3, None, 4, [2]]

从集合或列表中选择(集合论)

您可以从集合或列表中选择或组合项。

版本 1.4 中的新增功能。

从列表中获取唯一集合

# list1: [1, 2, 5, 1, 3, 4, 10]
{{ list1 | unique }}
# => [1, 2, 5, 3, 4, 10]

获取两个列表的并集

# list1: [1, 2, 5, 1, 3, 4, 10]
# list2: [1, 2, 3, 4, 5, 11, 99]
{{ list1 | union(list2) }}
# => [1, 2, 5, 1, 3, 4, 10, 11, 99]

获取两个列表的交集(两个列表中所有项的唯一列表)

# list1: [1, 2, 5, 3, 4, 10]
# list2: [1, 2, 3, 4, 5, 11, 99]
{{ list1 | intersect(list2) }}
# => [1, 2, 5, 3, 4]

获取两个列表的差集(第一个列表中不存在于第二个列表中的项)

# list1: [1, 2, 5, 1, 3, 4, 10]
# list2: [1, 2, 3, 4, 5, 11, 99]
{{ list1 | difference(list2) }}
# => [10]

获取两个列表的对称差集(每个列表独有的项)

# list1: [1, 2, 5, 1, 3, 4, 10]
# list2: [1, 2, 3, 4, 5, 11, 99]
{{ list1 | symmetric_difference(list2) }}
# => [10, 11, 99]

计算数字(数学)

版本 1.9 中的新增功能。

您可以使用 Ansible 过滤器计算数字的对数、幂和根。Jinja2 提供其他数学函数,如 abs() 和 round()。

获取对数(默认值为 e)

{{ 8 | log }}
# => 2.0794415416798357

获取以 10 为底的对数

{{ 8 | log(10) }}
# => 0.9030899869919435

给我 2 的幂! (或 5)

{{ 8 | pow(5) }}
# => 32768.0

平方根或 5 次方

{{ 8 | root }}
# => 2.8284271247461903

{{ 8 | root(5) }}
# => 1.5157165665103982

管理网络交互

这些过滤器可以帮助您完成常见的网络任务。

注意

这些过滤器已迁移到 ansible.utils 集合。请按照安装说明安装该集合。

IP 地址过滤器

版本 1.9 中的新增功能。

测试字符串是否为有效的 IP 地址

{{ myvar | ansible.utils.ipaddr }}

您还可以要求特定的 IP 协议版本

{{ myvar | ansible.utils.ipv4 }}
{{ myvar | ansible.utils.ipv6 }}

IP 地址过滤器也可以用于从 IP 地址中提取特定信息。例如,要从 CIDR 中获取 IP 地址本身,您可以使用

{{ '192.0.2.1/24' | ansible.utils.ipaddr('address') }}
# => 192.0.2.1

有关 ansible.utils.ipaddr 过滤器的更多信息和完整使用指南,请参阅 Ansible.Utils

网络 CLI 过滤器

版本 2.4 中的新增功能。

要将网络设备 CLI 命令的输出转换为结构化的 JSON 输出,请使用 ansible.netcommon.parse_cli 过滤器

{{ output | ansible.netcommon.parse_cli('path/to/spec') }}

The ansible.netcommon.parse_cli 过滤器将加载规范文件并将命令输出通过它传递,返回 JSON 输出。YAML 规范文件定义如何解析 CLI 输出。

规范文件应该是格式正确的 YAML。它定义了如何解析 CLI 输出并返回 JSON 数据。以下是一个有效的规范文件的示例,它将解析 show vlan 命令的输出。

---
vars:
  vlan:
    vlan_id: "{{ item.vlan_id }}"
    name: "{{ item.name }}"
    enabled: "{{ item.state != 'act/lshut' }}"
    state: "{{ item.state }}"

keys:
  vlans:
    value: "{{ vlan }}"
    items: "^(?P<vlan_id>\\d+)\\s+(?P<name>\\w+)\\s+(?P<state>active|act/lshut|suspended)"
  state_static:
    value: present

上面的规范文件将返回一个 JSON 数据结构,该结构是包含解析的 VLAN 信息的哈希列表。

可以使用 key 和 values 指令将相同命令解析为哈希。以下是如何使用相同的 show vlan 命令将输出解析为哈希值的示例。

---
vars:
  vlan:
    key: "{{ item.vlan_id }}"
    values:
      vlan_id: "{{ item.vlan_id }}"
      name: "{{ item.name }}"
      enabled: "{{ item.state != 'act/lshut' }}"
      state: "{{ item.state }}"

keys:
  vlans:
    value: "{{ vlan }}"
    items: "^(?P<vlan_id>\\d+)\\s+(?P<name>\\w+)\\s+(?P<state>active|act/lshut|suspended)"
  state_static:
    value: present

解析 CLI 命令的另一个常见用例是将大型命令分解为可以解析的块。这可以使用 start_blockend_block 指令来完成,这些指令可以将命令分解为可以解析的块。

---
vars:
  interface:
    name: "{{ item[0].match[0] }}"
    state: "{{ item[1].state }}"
    mode: "{{ item[2].match[0] }}"

keys:
  interfaces:
    value: "{{ interface }}"
    start_block: "^Ethernet.*$"
    end_block: "^$"
    items:
      - "^(?P<name>Ethernet\\d\\/\\d*)"
      - "admin state is (?P<state>.+),"
      - "Port mode is (.+)"

上面的示例将 show interface 的输出解析为哈希列表。

网络过滤器还支持使用 TextFSM 库解析 CLI 命令的输出。要使用 TextFSM 解析 CLI 输出,请使用以下过滤器

{{ output.stdout[0] | ansible.netcommon.parse_cli_textfsm('path/to/fsm') }}

使用 TextFSM 过滤器需要安装 TextFSM 库。

网络 XML 过滤器

版本 2.5 中的新增功能。

要将网络设备命令的 XML 输出转换为结构化的 JSON 输出,请使用 ansible.netcommon.parse_xml 过滤器

{{ output | ansible.netcommon.parse_xml('path/to/spec') }}

The ansible.netcommon.parse_xml 过滤器将加载规范文件并将命令输出通过它传递,格式化为 JSON。

规范文件应该是格式正确的 YAML。它定义了如何解析 XML 输出并返回 JSON 数据。

以下是一个有效的规范文件的示例,它将解析 show vlan | display xml 命令的输出。

---
vars:
  vlan:
    vlan_id: "{{ item.vlan_id }}"
    name: "{{ item.name }}"
    desc: "{{ item.desc }}"
    enabled: "{{ item.state.get('inactive') != 'inactive' }}"
    state: "{% if item.state.get('inactive') == 'inactive'%} inactive {% else %} active {% endif %}"

keys:
  vlans:
    value: "{{ vlan }}"
    top: configuration/vlans/vlan
    items:
      vlan_id: vlan-id
      name: name
      desc: description
      state: ".[@inactive='inactive']"

上面的规范文件将返回一个 JSON 数据结构,该结构是包含解析的 VLAN 信息的哈希列表。

可以使用 key 和 values 指令将相同命令解析为哈希。以下是如何使用相同的 show vlan | display xml 命令将输出解析为哈希值的示例。

---
vars:
  vlan:
    key: "{{ item.vlan_id }}"
    values:
        vlan_id: "{{ item.vlan_id }}"
        name: "{{ item.name }}"
        desc: "{{ item.desc }}"
        enabled: "{{ item.state.get('inactive') != 'inactive' }}"
        state: "{% if item.state.get('inactive') == 'inactive'%} inactive {% else %} active {% endif %}"

keys:
  vlans:
    value: "{{ vlan }}"
    top: configuration/vlans/vlan
    items:
      vlan_id: vlan-id
      name: name
      desc: description
      state: ".[@inactive='inactive']"

The value of top 是相对于 XML 根节点的 XPath。在下面的示例中,给出的 XML 输出,top 的值为 configuration/vlans/vlan,它是相对于根节点 (<rpc-reply>) 的 XPath 表达式。 configurationtop 值中最外面的容器节点,而 vlan 是最里面的容器节点。

items 是一个键值对字典,它将用户定义的名称映射到选择元素的 XPath 表达式。Xpath 表达式是相对于包含在 top 中的 XPath 值的值。例如,规范文件中的 vlan_id 是一个用户定义的名称,其值为 vlan-id,它是相对于 top 中的 XPath 值的值

可以使用 XPath 表达式提取 XML 标签的属性。规范文件中 state 的值是一个 XPath 表达式,用于获取输出 XML 中 vlan 标签的属性。

<rpc-reply>
  <configuration>
    <vlans>
      <vlan inactive="inactive">
       <name>vlan-1</name>
       <vlan-id>200</vlan-id>
       <description>This is vlan-1</description>
      </vlan>
    </vlans>
  </configuration>
</rpc-reply>

注意

有关支持的 XPath 表达式的更多信息,请参阅 XPath 支持

网络 VLAN 过滤器

版本 2.8 中的新功能。

使用 ansible.netcommon.vlan_parser 过滤器将 VLAN 整数的无序列表转换为根据类似 IOS 的 VLAN 列表规则排序的整数排序字符串列表。此列表具有以下属性

  • VLAN 按升序排列。

  • 三个或更多连续的 VLAN 使用连字符列出。

  • 列表的第一行可以有 first_line_len 个字符长。

  • 后续列表行可以有 other_line_len 个字符长。

排序 VLAN 列表

{{ [3003, 3004, 3005, 100, 1688, 3002, 3999] | ansible.netcommon.vlan_parser }}

此示例呈现以下排序列表

['100,1688,3002-3005,3999']

另一个示例 Jinja 模板

{% set parsed_vlans = vlans | ansible.netcommon.vlan_parser %}
switchport trunk allowed vlan {{ parsed_vlans[0] }}
{% for i in range (1, parsed_vlans | count) %}
switchport trunk allowed vlan add {{ parsed_vlans[i] }}
{% endfor %}

这允许在 Cisco IOS 标记接口上动态生成 VLAN 列表。您可以存储接口所需的精确 VLAN 的详尽原始列表,然后将其与将实际为配置生成的已解析 IOS 输出进行比较。

对字符串和密码进行哈希处理和加密

版本 1.9 中的新增功能。

获取字符串的 sha1 哈希

{{ 'test1' | hash('sha1') }}
# => "b444ac06613fc8d63795be9ad0beaf55011936ac"

获取字符串的 md5 哈希

{{ 'test1' | hash('md5') }}
# => "5a105e8b9d40e1329780d62ea2265d8a"

获取字符串校验和

{{ 'test2' | checksum }}
# => "109f4b3c50d7b0df729d299bc6f8e9ef9066971f"

其他哈希(平台相关)

{{ 'test2' | hash('blowfish') }}

获取 sha512 密码哈希(随机盐)

{{ 'passwordsaresecret' | password_hash('sha512') }}
# => "$6$UIv3676O/ilZzWEE$ktEfFF19NQPF2zyxqxGkAceTnbEgpEKuGBtk6MlU4v2ZorWaVQUMyurgmHCh2Fr4wpmQ/Y.AlXMJkRnIS4RfH/"

获取使用特定盐的 sha256 密码哈希

{{ 'secretpassword' | password_hash('sha256', 'mysecretsalt') }}
# => "$5$mysecretsalt$ReKNyDYjkKNqRVwouShhsEqZ3VOE8eoVO4exihOfvG4"

一种幂等方法,可以为每个系统生成唯一的哈希,即使用在运行之间一致的盐

{{ 'secretpassword' | password_hash('sha512', 65534 | random(seed=inventory_hostname) | string) }}
# => "$6$43927$lQxPKz2M2X.NWO.gK.t7phLwOKQMcSq72XxDZQ0XzYV6DlL1OD72h417aj16OnHTGxNzhftXJQBcjbunLEepM0"

可用的哈希类型取决于运行 Ansible 的控制系统,ansible.builtin.hash 依赖于 hashlibansible.builtin.password_hash 依赖于 passlib。如果未安装 passlib,则将 crypt 用作后备。

版本 2.7 中的新功能。

某些哈希类型允许提供 rounds 参数

{{ 'secretpassword' | password_hash('sha256', 'mysecretsalt', rounds=10000) }}
# => "$5$rounds=10000$mysecretsalt$Tkm80llAxD4YHll6AgNIztKn0vzAACsuuEfYeGP7tm7"

过滤器 password_hash 生成的结果取决于您是否安装了 passlib

为了确保幂等性,请指定 rounds 不为 cryptpasslib 的默认值,对于 crypt5000,对于 passlib 为可变值(对于 sha256 为 535000,对于 sha512 为 656000

{{ 'secretpassword' | password_hash('sha256', 'mysecretsalt', rounds=5001) }}
# => "$5$rounds=5001$mysecretsalt$wXcTWWXbfcR8er5IVf7NuquLvnUA6s8/qdtOhAZ.xN."

哈希类型‘blowfish’ (BCrypt) 提供了指定 BCrypt 算法版本的功能。

{{ 'secretpassword' | password_hash('blowfish', '1234567890123456789012', ident='2b') }}
# => "$2b$12$123456789012345678901uuJ4qFdej6xnWjOQT.FStqfdoY8dYUPC"

注意

该参数仅适用于 blowfish (BCrypt)。其他哈希类型将简单地忽略此参数。此参数的有效值为:[‘2’, ‘2a’, ‘2y’, ‘2b’]

版本 2.12 中的新增功能。

您也可以使用 Ansible ansible.builtin.vault 过滤器来加密数据

# simply encrypt my key in a vault
vars:
  myvaultedkey: "{{ keyrawdata|vault(passphrase) }}"

- name: save templated vaulted data
  template: src=dump_template_data.j2 dest=/some/key/vault.txt
  vars:
    mysalt: '{{ 2**256|random(seed=inventory_hostname) }}'
    template_data: '{{ secretdata|vault(vaultsecret, salt=mysalt) }}'

然后使用 unvault 过滤器对其进行解密

# simply decrypt my key from a vault
vars:
  mykey: "{{ myvaultedkey|unvault(passphrase) }}"

- name: save templated unvaulted data
  template: src=dump_template_data.j2 dest=/some/key/clear.txt
  vars:
    template_data: '{{ secretdata|unvault(vaultsecret) }}'

操作文本

多个过滤器可以处理文本,包括 URL、文件名和路径名。

向文件添加注释

The ansible.builtin.comment filter 允许您从模板中的文本创建文件中的注释,并提供多种注释样式。默认情况下,Ansible 使用 # 开始注释行并在注释文本的上方和下方添加一个空注释行。例如,以下内容

{{ "Plain style (default)" | comment }}

生成以下输出

#
# Plain style (default)
#

Ansible 提供 C (//...)、C 块 (/*...*/)、Erlang (%...) 和 XML (<!--...-->) 的注释样式

{{ "C style" | comment('c') }}
{{ "C block style" | comment('cblock') }}
{{ "Erlang style" | comment('erlang') }}
{{ "XML style" | comment('xml') }}

您可以定义自定义注释字符。此过滤器

{{ "My Special Case" | comment(decoration="! ") }}

生成

!
! My Special Case
!

您可以完全自定义注释样式

{{ "Custom style" | comment('plain', prefix='#######\n#', postfix='#\n#######\n   ###\n    #') }}

这将创建以下输出

#######
#
# Custom style
#
#######
   ###
    #

过滤器也可以应用于任何 Ansible 变量。例如,为了使 ansible_managed 变量的输出更易读,我们可以将 ansible.cfg 文件中的定义更改为

[defaults]

ansible_managed = This file is managed by Ansible.%n
  template: {file}
  date: %Y-%m-%d %H:%M:%S
  user: {uid}
  host: {host}

然后使用带 comment 过滤器的变量

{{ ansible_managed | comment }}

生成以下输出

#
# This file is managed by Ansible.
#
# template: /home/ansible/env/dev/ansible_managed/roles/role1/templates/test.j2
# date: 2015-09-10 11:02:58
# user: ansible
# host: myhost
#

对 URL 进行编码变量

The urlencode filter 使用 UTF-8 对数据进行引号以在 URL 路径或查询中使用

{{ 'Trollhättan' | urlencode }}
# => 'Trollh%C3%A4ttan'

分割 URL

版本 2.4 中的新增功能。

The ansible.builtin.urlsplit filter 从 URL 中提取片段、主机名、netloc、密码、路径、端口、查询、方案和用户名。没有参数时,返回所有字段的字典

{{ "http://user:[email protected]:9000/dir/index.html?query=term#fragment" | urlsplit('hostname') }}
# => 'www.acme.com'

{{ "http://user:[email protected]:9000/dir/index.html?query=term#fragment" | urlsplit('netloc') }}
# => 'user:[email protected]:9000'

{{ "http://user:[email protected]:9000/dir/index.html?query=term#fragment" | urlsplit('username') }}
# => 'user'

{{ "http://user:[email protected]:9000/dir/index.html?query=term#fragment" | urlsplit('password') }}
# => 'password'

{{ "http://user:[email protected]:9000/dir/index.html?query=term#fragment" | urlsplit('path') }}
# => '/dir/index.html'

{{ "http://user:[email protected]:9000/dir/index.html?query=term#fragment" | urlsplit('port') }}
# => '9000'

{{ "http://user:[email protected]:9000/dir/index.html?query=term#fragment" | urlsplit('scheme') }}
# => 'http'

{{ "http://user:[email protected]:9000/dir/index.html?query=term#fragment" | urlsplit('query') }}
# => 'query=term'

{{ "http://user:[email protected]:9000/dir/index.html?query=term#fragment" | urlsplit('fragment') }}
# => 'fragment'

{{ "http://user:[email protected]:9000/dir/index.html?query=term#fragment" | urlsplit }}
# =>
#   {
#       "fragment": "fragment",
#       "hostname": "www.acme.com",
#       "netloc": "user:[email protected]:9000",
#       "password": "password",
#       "path": "/dir/index.html",
#       "port": 9000,
#       "query": "query=term",
#       "scheme": "http",
#       "username": "user"
#   }

使用正则表达式搜索字符串

要使用正则表达式在字符串中搜索或提取字符串的部分,请使用 ansible.builtin.regex_search filter

# Extracts the database name from a string
{{ 'server1/database42' | regex_search('database[0-9]+') }}
# => 'database42'

# Example for a case insensitive search in multiline mode
{{ 'foo\nBAR' | regex_search('^bar', multiline=True, ignorecase=True) }}
# => 'BAR'

# Example for a case insensitive search in multiline mode using inline regex flags
{{ 'foo\nBAR' | regex_search('(?im)^bar') }}
# => 'BAR'

# Extracts server and database id from a string
{{ 'server1/database42' | regex_search('server([0-9]+)/database([0-9]+)', '\\1', '\\2') }}
# => ['1', '42']

# Extracts dividend and divisor from a division
{{ '21/42' | regex_search('(?P<dividend>[0-9]+)/(?P<divisor>[0-9]+)', '\\g<dividend>', '\\g<divisor>') }}
# => ['21', '42']

The ansible.builtin.regex_search filter 如果找不到匹配项则返回一个空字符串

{{ 'ansible' | regex_search('foobar') }}
# => ''

注意

The ansible.builtin.regex_search filter 在 Jinja 表达式中使用时(例如,与运算符、其他过滤器等结合使用)返回 None。请参阅下面的两个示例。

{{ 'ansible' | regex_search('foobar') == '' }}
# => False
{{ 'ansible' | regex_search('foobar') is none }}
# => True

这是由于历史行为和 Ansible 中对某些 Jinja 内部结构的自定义重新实现。如果希望 ansible.builtin.regex_search filter 始终返回 None(如果找不到匹配项),则启用 jinja2_native 设置。有关详细信息,请参阅 为什么 regex_search 过滤器返回 None 而不是空字符串?

要提取字符串中所有正则表达式匹配项的出现次数,请使用 ansible.builtin.regex_findall filter

# Returns a list of all IPv4 addresses in the string
{{ 'Some DNS servers are 8.8.8.8 and 8.8.4.4' | regex_findall('\\b(?:[0-9]{1,3}\\.){3}[0-9]{1,3}\\b') }}
# => ['8.8.8.8', '8.8.4.4']

# Returns all lines that end with "ar"
{{ 'CAR\ntar\nfoo\nbar\n' | regex_findall('^.ar$', multiline=True, ignorecase=True) }}
# => ['CAR', 'tar', 'bar']

# Returns all lines that end with "ar" using inline regex flags for multiline and ignorecase
{{ 'CAR\ntar\nfoo\nbar\n' | regex_findall('(?im)^.ar$') }}
# => ['CAR', 'tar', 'bar']

要使用正则表达式替换字符串中的文本,请使用 ansible.builtin.regex_replace filter

# Convert "ansible" to "able"
{{ 'ansible' | regex_replace('^a.*i(.*)$', 'a\\1') }}
# => 'able'

# Convert "foobar" to "bar"
{{ 'foobar' | regex_replace('^f.*o(.*)$', '\\1') }}
# => 'bar'

# Convert "localhost:80" to "localhost, 80" using named groups
{{ 'localhost:80' | regex_replace('^(?P<host>.+):(?P<port>\\d+)$', '\\g<host>, \\g<port>') }}
# => 'localhost, 80'

# Convert "localhost:80" to "localhost"
{{ 'localhost:80' | regex_replace(':80') }}
# => 'localhost'

# Comment all lines that end with "ar"
{{ 'CAR\ntar\nfoo\nbar\n' | regex_replace('^(.ar)$', '#\\1', multiline=True, ignorecase=True) }}
# => '#CAR\n#tar\nfoo\n#bar\n'

# Comment all lines that end with "ar" using inline regex flags for multiline and ignorecase
{{ 'CAR\ntar\nfoo\nbar\n' | regex_replace('(?im)^(.ar)$', '#\\1') }}
# => '#CAR\n#tar\nfoo\n#bar\n'

注意

如果要匹配整个字符串,并且您使用的是 *,请确保始终用开始/结束锚点将您的正则表达式包围起来。例如,^(.*)$ 将始终只匹配一个结果,而 (.*) 在某些 Python 版本上将匹配整个字符串和末尾的空字符串,这意味着它将进行两次替换

# add "https://" prefix to each item in a list
GOOD:
{{ hosts | map('regex_replace', '^(.*)$', 'https://\\1') | list }}
{{ hosts | map('regex_replace', '(.+)', 'https://\\1') | list }}
{{ hosts | map('regex_replace', '^', 'https://') | list }}

BAD:
{{ hosts | map('regex_replace', '(.*)', 'https://\\1') | list }}

# append ':80' to each item in a list
GOOD:
{{ hosts | map('regex_replace', '^(.*)$', '\\1:80') | list }}
{{ hosts | map('regex_replace', '(.+)', '\\1:80') | list }}
{{ hosts | map('regex_replace', '$', ':80') | list }}

BAD:
{{ hosts | map('regex_replace', '(.*)', '\\1:80') | list }}

注意

在 ansible 2.0 之前,如果 ansible.builtin.regex_replace 过滤器与 YAML 参数(而不是更简单的“键=值”参数)中的变量一起使用,那么您需要用 4 个反斜杠 (\\\\) 来转义反向引用(例如,\\1),而不是 2 个 (\\)。

新增于 2.0 版本。

要转义标准 Python 正则表达式中的特殊字符,请使用 ansible.builtin.regex_escape filter(使用默认的 re_type='python' 选项)

# convert '^f.*o(.*)$' to '\^f\.\*o\(\.\*\)\$'
{{ '^f.*o(.*)$' | regex_escape() }}

版本 2.8 中的新功能。

要转义 POSIX 基本正则表达式中的特殊字符,请使用 ansible.builtin.regex_escape filter,并使用 re_type='posix_basic' 选项

# convert '^f.*o(.*)$' to '\^f\.\*o(\.\*)\$'
{{ '^f.*o(.*)$' | regex_escape('posix_basic') }}

管理文件名和路径名

要获取文件路径的最后一个名称,例如“/etc/asdf/foo.txt”中的“foo.txt”

{{ path | basename }}

要获取 Windows 样式文件路径的最后一个名称(版本 2.0 中新增)

{{ path | win_basename }}

要将 Windows 驱动器号与文件路径的其余部分分开(版本 2.0 中新增)

{{ path | win_splitdrive }}

要仅获取 Windows 驱动器号

{{ path | win_splitdrive | first }}

要获取路径的其余部分,不包括驱动器号

{{ path | win_splitdrive | last }}

要从路径获取目录

{{ path | dirname }}

要从 Windows 路径获取目录(版本 2.0 中新增)

{{ path | win_dirname }}

要展开包含波浪号 (~) 字符的路径(版本 1.5 中新增)

{{ path | expanduser }}

要展开包含环境变量的路径

{{ path | expandvars }}

注意

expandvars 展开本地变量;对远程路径使用它可能会导致错误。

版本 2.6 中的新功能。

要获取链接的真实路径(版本 1.8 中新增)

{{ path | realpath }}

要获取链接的相对路径,从起点开始(版本 1.7 中新增)

{{ path | relpath('/etc') }}

要获取路径或文件名的根目录和扩展名(版本 2.0 中新增)

# with path == 'nginx.conf' the return would be ('nginx', '.conf')
{{ path | splitext }}

The ansible.builtin.splitext filter 始终返回一对字符串。可以使用 firstlast 过滤器访问各个组件

# with path == 'nginx.conf' the return would be 'nginx'
{{ path | splitext | first }}

# with path == 'nginx.conf' the return would be '.conf'
{{ path | splitext | last }}

要连接一个或多个路径组件

{{ ('/etc', path, 'subdir', file) | path_join }}

版本 2.10 中新增。

操作字符串

要为 shell 使用添加引号

- name: Run a shell command
  ansible.builtin.shell: echo {{ string_value | quote }}

(文档:ansible.builtin.quote)

要将列表连接成字符串

{{ list | join(" ") }}

要将字符串拆分成列表

{{ csv_string | split(",") }}

版本 2.11 中的新增功能。

要处理 Base64 编码字符串

{{ encoded | b64decode }}
{{ decoded | string | b64encode }}

(文档:ansible.builtin.b64encode)

从版本 2.6 开始,您可以定义要使用的编码类型,默认值为 utf-8

{{ encoded | b64decode(encoding='utf-16-le') }}
{{ decoded | string | b64encode(encoding='utf-16-le') }}

(文档:ansible.builtin.b64decode)

注意

The string filter 仅在 Python 2 中需要,并确保要编码的文本是 unicode 字符串。在 b64encode 之前没有该过滤器,将编码错误的值。

注意

b64decode 的返回值是字符串。如果您使用 b64decode 解密二进制 blob,然后尝试使用它(例如,使用 copy 将其写入文件),您很可能会发现您的二进制文件已损坏。如果您需要获取 base64 编码的二进制文件并将其写入磁盘,最好使用系统 base64 命令与 shell 模块 一起使用,使用 stdin 参数将编码数据传入。例如:shell: cmd="base64 --decode > myfile.bin" stdin="{{ encoded }}"

版本 2.6 中的新功能。

管理 UUID

要创建命名空间 UUIDv5

{{ string | to_uuid(namespace='11111111-2222-3333-4444-555555555555') }}

版本 2.10 中新增。

要使用默认的 Ansible 命名空间“361E6D51-FAEC-444A-9079-341386DA8E2E”创建命名空间 UUIDv5

{{ string | to_uuid }}

版本 1.9 中的新增功能。

要使用复杂变量列表中每个项目的某个属性,请使用 Jinja2 map filter

# get a comma-separated list of the mount points (for example, "/,/mnt/stuff") on a host
{{ ansible_mounts | map(attribute='mount') | join(',') }}

处理日期和时间

要从字符串获取日期对象,请使用 to_datetime 过滤器

# Get the total amount of seconds between two dates. Default date format is %Y-%m-%d %H:%M:%S but you can pass your own format
{{ (("2016-08-14 20:00:12" | to_datetime) - ("2015-12-25" | to_datetime('%Y-%m-%d'))).total_seconds()  }}

# Get remaining seconds after delta has been calculated. NOTE: This does NOT convert years, days, hours, and so on to seconds. For that, use total_seconds()
{{ (("2016-08-14 20:00:12" | to_datetime) - ("2016-08-14 18:00:00" | to_datetime)).seconds  }}
# This expression evaluates to "12" and not "132". Delta is 2 hours, 12 seconds

# get amount of days between two dates. This returns only the number of days and discards remaining hours, minutes, and seconds
{{ (("2016-08-14 20:00:12" | to_datetime) - ("2015-12-25" | to_datetime('%Y-%m-%d'))).days  }}

注意

有关使用 Python 日期格式字符串的完整格式代码列表,请参阅 python 日期时间文档.

版本 2.4 中的新增功能。

要使用字符串格式化日期(如使用 shell date 命令),请使用“strftime”过滤器

# Display year-month-day
{{ '%Y-%m-%d' | strftime }}
# => "2021-03-19"

# Display hour:min:sec
{{ '%H:%M:%S' | strftime }}
# => "21:51:04"

# Use ansible_date_time.epoch fact
{{ '%Y-%m-%d %H:%M:%S' | strftime(ansible_date_time.epoch) }}
# => "2021-03-19 21:54:09"

# Use arbitrary epoch value
{{ '%Y-%m-%d' | strftime(0) }}          # => 1970-01-01
{{ '%Y-%m-%d' | strftime(1441357287) }} # => 2015-09-04

版本 2.13 中的新功能。

strftime 接受一个可选的 utc 参数,默认值为 False,这意味着时间位于本地时区

{{ '%H:%M:%S' | strftime }}           # time now in local timezone
{{ '%H:%M:%S' | strftime(utc=True) }} # time now in UTC

注意

要获取所有字符串可能性,请查看 https://docs.pythonlang.cn/3/library/time.html#time.strftime

获取 Kubernetes 资源名称

注意

这些过滤器已迁移到 kubernetes.core 集合。按照安装说明安装该集合。

使用“k8s_config_resource_name”过滤器获取 Kubernetes ConfigMap 或 Secret 的名称,包括其哈希值

{{ configmap_resource_definition | kubernetes.core.k8s_config_resource_name }}

然后可以使用它来引用 Pod 规范中的哈希值

my_secret:
  kind: Secret
  metadata:
    name: my_secret_name

deployment_resource:
  kind: Deployment
  spec:
    template:
      spec:
        containers:
        - envFrom:
            - secretRef:
                name: {{ my_secret | kubernetes.core.k8s_config_resource_name }}

版本 2.8 中的新功能。

另请参阅

Ansible 剧本

剧本简介

条件

剧本中的条件语句

使用变量

关于变量的一切

循环

剧本中的循环

角色

按角色组织剧本

一般提示

剧本的技巧和窍门

交流

有问题吗?需要帮助吗?想分享你的想法吗?访问 Ansible 交流指南

Python 3 正则表达式操作

如何使用内联正则表达式标志