Jinja 过滤器

Jinja 过滤器提供了一种在 rulebook 的 action 中转换和操作数据的方法。这些过滤器可用于格式化字符串、提取文件路径的部分内容,以及在将事件数据用于 action 之前对其执行正则替换。

注意

Jinja 过滤器可以用在 rulebook 的 actions 中,但 不能 用于 conditions(条件)。条件必须使用规则引擎提供的原生条件运算符和测试。

在 Actions 中的用法

Jinja 过滤器在 action 中使用标准的 Jinja2 语法,通过管道 (|) 运算符调用。您可以将多个过滤器链接在一起以执行复杂的转换。

示例

action:
  debug:
    msg: "{{ event.name | upper | replace('HELLO', 'GOODBYE') }}"

可用过滤器

除了所有标准的 Python 字符串方法和内置的 Jinja2 过滤器外,ansible-rulebook 还提供了自定义的 Jinja 过滤器。这些自定义过滤器包括:

  • regex_replace

  • basename

  • dirname

  • normpath

regex_replace

对字符串值执行正则表达式替换。

参数

描述

必填

pattern

要搜索的正则表达式模式

replacement

替换字符串

count

要替换的最大出现次数(0 表示全部替换)。默认值:0

ignore_case

执行不区分大小写的匹配。默认值:false

multiline

为正则启用多行模式。默认值:false

mandatory_count

要求的最小替换次数(若未达到则报错)。默认值:0

示例

action:
  debug:
    msg: "{{ event.name | regex_replace('host1', 'host195') }}"
action:
  post_event:
    event:
      msg: "{{ event.name | regex_replace('Bamm', 'Betty', count=1) }}"

basename

从文件路径中提取基本名称(文件名)。

示例

# Input: "/etc/certs/cert.pem"
# Output: "cert.pem"
action:
  debug:
    msg: "{{ event.filepath | basename }}"
action:
  post_event:
    event:
      basename: "{{ event.filename | normpath | basename }}"

dirname

从文件路径中提取目录名称。

示例

# Input: "/etc/certs/cert.pem"
# Output: "/etc/certs"
action:
  debug:
    msg: "{{ event.filepath | dirname }}"
# Chaining filters: first normalize, then get dirname
action:
  post_event:
    event:
      dirname: "{{ event.filename | normpath | dirname }}"

注意

如果仅提供了不含路径的文件名,dirname 将返回空字符串。

normpath

通过折叠冗余的分隔符和上级引用来规范化文件路径。

示例

# Input: "/abc//def//jhk/test.txt"
# Output: "/abc/def/jhk/test.txt"
action:
  debug:
    msg: "{{ event.filepath | normpath }}"
action:
  post_event:
    event:
      normal: "{{ event.filename | normpath }}"

Python 字符串方法

除了上述自定义过滤器外,所有 Python 字符串方法均可用作过滤器。常见示例包括:

  • upper - 转换为大写

  • lower - 转换为小写

  • capitalize - 首字母大写

  • replace(old, new) - 替换子字符串的出现实例

  • split(separator) - 将字符串拆分为列表

示例

action:
  debug:
    msg:
      - "{{ event.name | replace('.com', '') }}"
      - "{{ event.name.split('.') | first }}"
      - "{{ event.name | capitalize }}"

过滤器链

可以通过使用多个管道运算符将过滤器链在一起。每个过滤器处理链中前一个过滤器的输出。

示例

action:
  post_event:
    event:
      # First normalize the path, then get the directory, then convert to uppercase
      clean_dir: "{{ event.filename | normpath | dirname | upper }}"

完整示例

示例 1:使用正则和字符串方法进行字符串操作

---
- name: 97 jinja
  hosts: all
  sources:
    - eda.builtin.generic:
        payload:
           - name: "host1.net"
           - name: "Bamm Bamm Rubble"
        create_index: index
        shutdown_delay: 5
  rules:
    - name: regex rule
      condition: event.name is regex("host")
      actions:
        - debug:
            msg:
              - "{{ event.name | replace('.com', '') }}"
              - "{{ event.name.split('.') | first }}"
              - "{{ event.name | capitalize }}"
              - "{{ event.name | regex_replace('host1', 'host195') }}"
    - name: original event
      condition: event.name == "Bamm Bamm Rubble"
      actions:
        - post_event:
             event:
                msg: "{{ event.name | regex_replace('Bamm', 'Betty', count=1) }}"
    - name: posted event
      condition: event.msg == "Betty Bamm Rubble"
      action:
        print_event:

示例 2:文件路径操作

---
- name: 98 jinja files
  hosts: all
  sources:
    - eda.builtin.generic:
        payload:
           - filename: "/abc//def//jhk/test.txt"
        create_index: index
        shutdown_delay: 5
  rules:
    - name: basename
      condition: event.basename == "test.txt"
      actions:
        - print_event:
    - name: dirname
      condition: event.dirname == "/abc/def/jhk"
      actions:
        - print_event:
    - name: normpath
      condition: event.normal == "/abc/def/jhk/test.txt"
      actions:
        - print_event:
    - name: catch_all
      condition: true
      actions:
        - post_event:
            event:
              normal: "{{ event.filename | normpath }}"
        - post_event:
            event:
              dirname: "{{ event.filename | normpath | dirname }}"
        - post_event:
            event:
              basename: "{{ event.filename | normpath | basename }}"

内置 Jinja2 过滤器

ansible-rulebook 还支持标准 Jinja2 过滤器。一些常用过滤器包括:

  • default(value) - 如果变量未定义,则提供默认值

  • first - 获取列表的第一项

  • last - 获取列表的最后一项

  • length - 获取列表或字符串的长度

  • join(separator) - 将列表合并为字符串

有关 Jinja2 过滤器的完整列表,请参阅 Jinja2 文档

示例

action:
  debug:
    msg: "{{ event.items | default([]) | length }}"

常见问题解答 (FAQ)

问: 我可以在 condition 中使用 Jinja 过滤器吗?
答: 不行,Jinja 过滤器不能用于 condition。Condition 使用规则引擎原生的
运算符和测试。您只能在 action 中使用 Jinja 过滤器在数据使用前对其进行转换。
问: 如果 Jinja 过滤器接收到 None 值会发生什么?
答: 自定义过滤器 (regex_replace, basename, dirname, normpath) 会通过
返回空字符串来优雅地处理 None 值。对于其他过滤器,您应该使用 default 过滤器
来提供一个回退值。
问: 我可以创建自定义 Jinja 过滤器吗?
答: 目前,ansible-rulebook 提供了上述四个自定义过滤器。对于其他
转换,您可以使用 Python 字符串方法、内置 Jinja2 过滤器或将多个
过滤器链在一起。
问: 我该如何处理 regex_replace 中的错误?
答: 您可以使用 mandatory_count 参数来确保至少发生一定次数的替换
。如果未达到强制计数,将抛出错误。如果没有此参数,
如果未找到匹配项,过滤器将返回原始字符串。