一、什么是 Jinja2 过滤器?
Jinja2 过滤器(Filters) 是一种用于对模板变量进行格式化或转换的工具。
在 Ansible 中,它们常用于:
- 对用户输入做默认值处理;
- 转换数据类型(如字符串转数字);
- 操作字符串、列表、字典等结构;
- 加密、路径处理、网络地址解析等高级操作。
📌 语法 :
{``{ 变量 | 过滤器(参数) }}
二、为什么需要过滤器?------核心价值
🎯 场景示例:安装软件包(带默认值)
yaml
- name: install packages
hosts: node02
gather_facts: no
tasks:
- name: install web pkgs
yum:
name: "{{ web_name | default('nginx') }}"
state: present
- 如果用户传入
web_name=apache→ 安装 apache; - 如果未传入 → 自动安装 nginx(默认值)。
✅ 优势:
- 避免变量未定义导致 playbook 失败;
- 提高 playbook 的灵活性与健壮性。
三、常用过滤器分类详解
🔹 1. 默认值过滤器:default
| 过滤器 | 作用 | 示例 |
|---|---|---|
default(value) |
若变量未定义或为空,则使用默认值 | `{``{ mysql_port |
💡 注意:若变量为
None或空字符串(""),也会触发默认值(除非设置default(..., true)忽略空值)。
🔹 2. 字符串操作过滤器
| 过滤器 | 作用 | 示例 |
|---|---|---|
upper |
转大写 | `"hello" |
lower |
转小写 | `"HELLO" |
capitalize |
首字母大写 | `"hello" |
reverse |
倒序 | `"abc" |
first / last |
取首/尾字符 | `"abc" |
trim |
去除首尾空格 | `" abc " |
center(30) |
居中并补空格至30位 | `"hi" |
length |
返回长度 | `"abc" |
list |
转为字符列表 | `"ab" |
shuffle |
随机打乱字符顺序 | `"abc" |
✅ 使用场景:日志格式化、用户名标准化、配置文件内容预处理。
🔹 3. 数字操作过滤器
| 过滤器 | 作用 | 示例 |
|---|---|---|
int |
转整数(失败可设默认) | `'8.6' |
float |
转浮点数 | `'8' |
abs |
绝对值 | `-5 |
round |
四舍五入 | `3.14159 |
random |
生成随机数 | `100 |
✅ 使用场景:端口计算、随机密码生成、数值校验。
🔹 4. 列表操作过滤器
| 过滤器 | 作用 | 示例 |
|---|---|---|
length |
列表长度 | `[1,2,3] |
first / last |
取首/尾元素 | `[1,2,3] |
min / max |
最小/最大值 | `[3,1,2] |
sort |
排序(reverse=true 降序) |
`[3,1,2] |
sum |
求和 | `[1,2,3] |
flatten |
扁平化嵌套列表 | `[[1,2],[3]] |
join(',') |
合并为字符串 | `['a','b'] |
random |
随机取一个元素 | `[1,2,3] |
shuffle |
随机打乱顺序 | `[1,2,3] |
union |
集合并集运算 | `{``{ [1,2,3] |
intersect |
集合交集运算 | `{``{ [1,2,3] |
difference |
集合差集运算 | `{``{ [1,2,3] |
symmetric_difference |
集合对称差运算 | `{``{ [1,2,3] |
✅ 使用场景:合并多个服务列表、去重、权限组交集判断。
🧩 集合运算示例:
yaml
vars:
group_a: [dev, ops, admin]
group_b: [ops, qa, admin]
tasks:
- debug: msg="{{ group_a | union(group_b) }}" # [dev, ops, admin, qa]
- debug: msg="{{ group_a | intersect(group_b) }}" # [ops, admin]
- debug: msg="{{ group_a | difference(group_b) }}" # [dev]
- debug: msg="{{ group_a | symmetric_difference(group_b) }}" # [dev, qa]
🔹 5. 注册变量状态过滤器(⚠️ Ansible 2.9+ 已弃用)
| 过滤器 | 作用 |
|---|---|
failed |
任务是否失败 |
changed |
任务是否变更 |
success |
任务是否成功 |
skipped |
任务是否跳过 |
⚠️ 替代方案 :直接使用
register_result is failed等条件判断。
🔹 6. 文件路径过滤器
| 过滤器 | 作用 | 示例 |
|---|---|---|
basename |
取文件名 | `/etc/passwd |
dirname |
取目录路径 | `/etc/passwd |
expanduser |
展开 ~ |
`"~/.bashrc" |
realpath |
解析软链接真实路径 | `/etc/localtime |
✅ 使用场景:动态构建日志路径、备份脚本路径处理。
🔹 7. 加解密过滤器
| 过滤器 | 作用 | 示例 |
|---|---|---|
hash('sha256') |
通用哈希 | `"secret" |
password_hash('sha512') |
密码加密(用于 user 模块) | `"123456" |
b64encode / b64decode |
Base64 编解码 | `"hello" |
✅ 使用场景:安全存储密码、API Token 编码传输。
🔹 8. 网络地址过滤器(需安装 python3-netaddr)
控制节点执行:
pip3 install netaddr
| 表达式 | 作用 | 示例(输入:192.168.1.10/24) |
|---|---|---|
ipaddr |
验证并返回标准格式 | "192.168.1.10/24" |
ipaddr('network') |
网络地址 | "192.168.1.0" |
ipaddr('netmask') |
子网掩码 | "255.255.255.0" |
ipaddr('broadcast') |
广播地址 | "192.168.1.255" |
ipaddr('size') |
可用 IP 数 | 256 |
ipaddr('host') |
主机地址+掩码 | "192.168.1.10/24" |
ipaddr('ipv4') |
强制 IPv4 | 同上 |
✅ 使用场景:自动生成防火墙规则、DHCP 范围计算。
🔹 9. URL 解析过滤器
| 过滤器 | 作用 | 示例(URL: https://user:pass@www.example.com:8080/path?query=1) |
|---|---|---|
urlsplit('hostname') |
域名 | "www.example.com" |
urlsplit('port') |
端口 | 8080 |
urlsplit('scheme') |
协议 | "https" |
urlsplit('path') |
路径 | "/path" |
urlsplit('query') |
查询参数 | "query=1" |
urlsplit('netloc') |
完整主机部分 | "user:pass@www.example.com:8080" |
✅ 使用场景:解析 API 地址、动态构建服务 URL。
🔹 10. 查找与替换过滤器(支持正则)
| 过滤器 | 作用 | 示例 |
|---|---|---|
replace("old", "new") |
普通替换 | `"hello world" |
regex_replace(r'\d+', '#') |
正则替换 | `"abc123" |
regex_search(r'\w+') |
搜索第一个匹配 | `"ID: 123" |
regex_findall(r'\d+') |
查找所有匹配 | `"a1b2c3" |
✅ 使用场景:日志提取、配置文件动态修改、敏感信息脱敏。
🔹 11. 字典操作过滤器
| 过滤器 | 作用 | 示例 |
|---|---|---|
combine(other_dict) |
合并字典(后者覆盖前者) | `{"a":1} |
dict2items |
字典 → 列表(每项含 key/value) | `{"name":"tom"} |
items2dict |
列表 → 字典 | 上述结果反向转换 |
to_json / to_yaml |
转 JSON/YAML 字符串 | 用于调试或写入文件 |
to_nice_json |
格式化易读 JSON | 适合 human-readable 输出 |
from_json / from_yaml |
从字符串解析结构 | 读取外部配置文件 |
✅ 使用场景:动态生成配置、合并多来源配置、API 数据处理。
🔹 12. 自定义过滤器(Python 开发)
步骤:
-
在
ansible.cfg中指定插件路径:ini[defaults] filter_plugins = ./plugins/filter -
创建
./plugins/filter/my_filters.py:pythondef to_uppercase(value): return str(value).upper() class FilterModule: def filters(self): return { 'to_uppercase': to_uppercase } -
在 playbook 中使用:
yaml- debug: msg: "{{ 'hello' | to_uppercase }}" # 输出: HELLO
✅ 使用场景:企业特定逻辑封装(如合规检查、特殊编码规则)。
四、综合使用场景举例
场景 1:动态生成 Nginx 配置
jinja2
server {
listen {{ port | default(80) }};
server_name {{ domain | lower | default('localhost') }};
root /var/www/{{ app_name | default('default') }};
}
场景 2:安全密码处理
yaml
- name: create user with encrypted password
user:
name: alice
password: "{{ 'MyPass123' | password_hash('sha512') }}"
场景 3:IP 地址自动分配
yaml
- set_fact:
network_base: "{{ ip_range | ipaddr('network') }}"
gateway: "{{ ip_range | ipaddr('gateway') }}"
五、练习题(巩固掌握)
📝 基础题
- 写一个 playbook,要求用户输入一个字符串,若未输入则默认为
"default_value",并将其转为大写输出。 - 将列表
[10, 5, 8, 3]排序后取最大值,并计算总和。 - 使用
b64encode对"ansible"进行编码,再用b64decode解码验证。
📝 进阶题
- 给定路径
/opt/app/config.yaml,使用过滤器分别提取目录名和文件名。 - 用户输入一个 IP 地址(如
10.0.0.5/24),自动计算其子网、广播地址和可用 IP 数量。 - 将字典
{"name": "Tom", "age": 25}转换为 YAML 格式并美化输出。
📝 挑战题
- 编写一个自定义过滤器
mask_ip,将 IP 地址192.168.1.10转为192.168.1.xxx。 - 从 URL
https://api.example.com/v1/users?id=123&token=abc中提取id和token参数(提示:先urlsplit('query'),再用split或正则)。
六、总结
| 类别 | 关键过滤器 | 应用价值 |
|---|---|---|
| 默认处理 | default |
防止变量缺失 |
| 数据转换 | int, float, upper, lower |
类型适配、格式统一 |
| 结构操作 | join, sort, combine, flatten |
动态构建复杂数据 |
| 安全加密 | password_hash, b64encode |
安全合规 |
| 网络/路径 | ipaddr, basename |
自动化运维核心 |
| 正则处理 | regex_replace |
灵活文本处理 |
| 自定义扩展 | Python 插件 | 企业级定制能力 |
💡 记住:过滤器是 Ansible 实现"声明式 + 灵活性"的关键工具!