[TOC]
常用过滤器一(filters)
描述:”过滤器(filters)”可以帮助我们对数据进行处理,ansible中的过滤器功能来自于jinja2模板引擎
,我们可以借助jinja2的过滤器功能在ansible中对数据进行各种处理;很多其他的过滤器有些是jinja2内置的有些是ansible特有,变量和过滤器之间采用类似于管道符进行拼接;
(1)字符串操作有关的过滤器:
- upper 过滤器 : 将所有小写字母都被变成了大写
- lower 过滤器 : 将所有大写字母都被变成了小写
- capitalize 过滤器 : 将字符串变成首字母大写,之后所有字母纯小写
- reverse 过滤器 : 将字符串反转
- list 过滤器 : 将字符串转换成列表,每个字符作为一个元素
- shuffle 过滤器 : 字面意思为洗牌,将字符串转换成列表每个字符作为一个元素,并且随机打乱顺序 #在随机打乱顺序时将ansible_date_time.epoch的值设置为随机种子
- first 过滤器 : 返回字符串的第一个字符
- last 过滤器 : 返回字符串的最后一个字符
- length 过滤器 : 返回字符串长度,length与count等效,可以写为count
- center(width=30) : 将字符串放在中间,并且设置字符串的长度默认以0补齐
(2)数字操作有关的过滤器
- int,int(default=6) : 将对应的值转换成int类型,将对应的值转换成int类型,如果无法转换,默认返回0
- float,float(8.88) : 将对应的值转换成浮点型,如果无法转换,默认返回’0.0’,当对应的值无法被转换成浮点型时,则返回指定值’8.8‘
- abs : 获取对应数值的绝对值
- round,round(5): 四舍五入或者取小数点后
- random(seed=(ansible_date_time.epoch)),random(start=5),random(start=5,step=3): 随机返回一个随机数并且可以设置步长,同样可以设置随机数种子
(3)与列表相关的过滤器
- length,first,last,random,shuffle,upper,lower : 与前面意思相同不同在于是列表
- min : 返回列表中最小的值
- max : 返回列表中最大的值
- sort, sort(reverse=true) :将列表升序排序输出,将列表降序排序输出
- sum : 返回纯数字非嵌套列表中所有数字的和
- flatten : 那么使用flatten可以’拉平’嵌套的列表
- join, join(‘ , ‘) : 列表元素合成字符串还可以每个元素之间用指定的字符隔开;
- unique : 去掉列表中重复的元素,重复的元素只留下一个
- union(testvar12) : 两个列表的并集
- intersect(testvar12) : 两个列表的交集
- symmetric_difference(testvar12) : 去除两个列表的补集
- difference(testvar12) : 两个列表的交集在列表1中的补集
(4)变量未定义时相关操作的过滤器
- default(‘WeiyiGeek’) : 如果变量没有定义,则临时返回一个指定的默认值
- mandatory : 如果对应的变量未定义,则报出“Mandatory variable not defined.”错误
基础示例1:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51# cat >filtersString.yml<<END
- hosts: local
remote_user: root
gather_facts: no
vars:
testvar: "abc123ABC 666"
testvar1: " abc "
testvar2: '123456789'
testvar3: "1a2b,@#$%^&"
tasks:
- debug:
#将字符串转换成纯大写.将获取到的变量的值中的所有字母都变成大写
msg: "{{ testvar | upper }}"
- debug:
#将字符串转换成纯小写
msg: "{{ testvar | lower }}"
- debug:
#将字符串变成首字母大写,之后所有字母纯小写
msg: "{{ testvar | capitalize }}"
- debug:
#将字符串反转
msg: "{{ testvar | reverse }}"
- debug:
#返回字符串的第一个字符
msg: "{{ testvar | first }}"
- debug:
#返回字符串的最后一个字符
msg: "{{ testvar | last }}"
- debug:
#将字符串开头和结尾的空格去除
msg: "{{ testvar1 | trim }}"
- debug:
#将字符串放在中间,并且设置字符串的长度为30,字符串两边用空格补齐30位长
msg: "{{ testvar1 | center(width=30) }}"
- debug:
#返回字符串长度,length与count等效,可以写为count
msg: "{{ testvar2 | length }}"
- debug:
#将字符串转换成列表,每个字符作为一个元素
msg: "{{ testvar3 | list }}"
- debug:
#将字符串转换成列表,每个字符作为一个元素,并且随机打乱顺序
#shuffle的字面意思为洗牌
msg: "{{ testvar3 | shuffle }}"
- debug:
#将字符串转换成列表,每个字符作为一个元素,并且随机打乱顺序
#在随机打乱顺序时,将ansible_date_time.epoch的值设置为随机种子
#也可以使用其他值作为随机种子,ansible_date_time.epoch是facts信息
msg: "{{ testvar3 | shuffle(seed=(ansible_date_time.epoch)) }}
END
基础示例1:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50#cat >filtersNumber.yml<<END
- hosts: test70
remote_user: root
vars:
testvar4: -1
tasks:
- debug:
#将对应的值转换成int类型
#ansible中,字符串和整形不能直接计算,比如{{ 8+'8' }}会报错
#所以,我们可以把一个值为数字的字符串转换成整形后再做计算
msg: "{{ 8+('8' | int) }}"
- debug:
#将对应的值转换成int类型,如果无法转换,默认返回0
#使用int(default=6)或者int(6)时,如果无法转换则返回指定值6
msg: "{{ 'a' | int(default=6) }}"
- debug:
#将对应的值转换成浮点型,如果无法转换,默认返回'0.0'
msg: "{{ '8' | float }}"
- debug:
#当对应的值无法被转换成浮点型时,则返回指定值’8.8‘
msg: "{{ 'a' | float(8.88) }}"
- debug:
#获取对应数值的绝对值
msg: "{{ testvar4 | abs }}"
- debug:
#四舍五入
msg: "{{ 12.5 | round }}"
- debug:
#取小数点后五位
msg: "{{ 3.1415926 | round(5) }}"
- debug:
#从0到100中随机返回一个随机数
msg: "{{ 100 | random }}"
- debug:
#从5到10中随机返回一个随机数
msg: "{{ 10 | random(start=5) }}"
- debug:
#从5到15中随机返回一个随机数,步长为3
#步长为3的意思是返回的随机数只有可能是5、8、11、14中的一个
msg: "{{ 15 | random(start=5,step=3) }}"
- debug:
#从0到15中随机返回一个随机数,这个随机数是5的倍数
msg: "{{ 15 | random(step=5) }}"
- debug:
#从0到15中随机返回一个随机数,并将ansible_date_time.epoch的值设置为随机种子
#也可以使用其他值作为随机种子,ansible_date_time.epoch是facts信息
#seed参数从ansible2.3版本开始可用
msg: "{{ 15 | random(seed=(ansible_date_time.epoch)) }}"
END
基础示例2:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97cat >filtersList.yml<<END
- hosts: local
remote_user: root
vars:
testvar7: [22,18,5,33,27,30]
testvar8: [1,[7,2,[15,9]],3,5]
testvar9: [1,'b',5]
testvar10: [1,'A','b',['QQ','wechat'],'CdEf']
testvar11: ['abc',1,3,'a',3,'1','abc']
testvar12: ['abc',2,'a','b','a']
tasks:
- debug:
#返回列表长度,length与count等效,可以写为count
msg: "{{ testvar7 | length }}"
- debug:
#返回列表中的第一个值
msg: "{{ testvar7 | first }}"
- debug:
#返回列表中的最后一个值
msg: "{{ testvar7 | last }}"
- debug:
#返回列表中最小的值
msg: "{{ testvar7 | min }}"
- debug:
#返回列表中最大的值
msg: "{{ testvar7 | max }}"
- debug:
#将列表升序排序输出
msg: "{{ testvar7 | sort }}"
- debug:
#将列表降序排序输出
msg: "{{ testvar7 | sort(reverse=true) }}"
- debug:
#返回纯数字非嵌套列表中所有数字的和
msg: "{{ testvar7 | sum }}"
- debug:
#如果列表中包含列表,那么使用flatten可以'拉平'嵌套的列表
#2.5版本中可用,执行如下示例后查看效果
msg: "{{ testvar8 | flatten }}"
- debug:
#如果列表中嵌套了列表,那么将第1层的嵌套列表‘拉平’
#2.5版本中可用,执行如下示例后查看效果
msg: "{{ testvar8 | flatten(levels=1) }}"
- debug:
#过滤器都是可以自由结合使用的,就好像linux命令中的管道符一样
#如下,取出嵌套列表中的最大值
msg: "{{ testvar8 | flatten | max }}"
- debug:
#将列表中的元素合并成一个字符串
msg: "{{ testvar9 | join }}"
- debug:
#将列表中的元素合并成一个字符串,每个元素之间用指定的字符隔开
msg: "{{ testvar9 | join(' , ') }}"
- debug:
#从列表中随机返回一个元素
#对列表使用random过滤器时,不能使用start和step参数
msg: "{{ testvar9 | random }}"
- debug:
#从列表中随机返回一个元素,并将ansible_date_time.epoch的值设置为随机种子
#seed参数从ansible2.3版本开始可用
msg: "{{ testvar9 | random(seed=(ansible_date_time.epoch)) }}"
- debug:
#随机打乱顺序列表中元素的顺序
#shuffle的字面意思为洗牌
msg: "{{ testvar9 | shuffle }}"
- debug:
#随机打乱顺序列表中元素的顺序
#在随机打乱顺序时,将ansible_date_time.epoch的值设置为随机种子
#seed参数从ansible2.3版本开始可用
msg: "{{ testvar9 | shuffle(seed=(ansible_date_time.epoch)) }}"
- debug:
#将列表中的每个元素变成纯大写
msg: "{{ testvar10 | upper }}"
- debug:
#将列表中的每个元素变成纯小写
msg: "{{ testvar10 | lower }}"
- debug:
#去掉列表中重复的元素,重复的元素只留下一个
msg: "{{ testvar11 | unique }}"
- debug:
#将两个列表合并,重复的元素只留下一个
#也就是求两个列表的并集
msg: "{{ testvar11 | union(testvar12) }}"
- debug:
#取出两个列表的交集,重复的元素只留下一个
msg: "{{ testvar11 | intersect(testvar12) }}"
- debug:
#取出存在于testvar11列表中,但是不存在于testvar12列表中的元素
#去重后重复的元素只留下一个
#换句话说就是:两个列表的交集在列表1中的补集
msg: "{{ testvar11 | difference(testvar12) }}"
- debug:
#取出两个列表中各自独有的元素,重复的元素只留下一个
#即去除两个列表的交集,剩余的元素
msg: "{{ testvar11 | symmetric_difference(testvar12) }}"
END
基础示例3:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20cat >filtersVarible.yml<<END
- hosts: test70
remote_user: root
gather_facts: no
vars:
testvar6: ''
tasks:
- debug:
#如果变量没有定义,则临时返回一个指定的默认值
#注:如果定义了变量,变量值为空字符串,则会输出空字符
#default过滤器的别名是d
msg: "{{ testvar5 | default('WeiyiGeek') }}"
- debug:
#如果变量的值是一个空字符串或者变量没有定义,则临时返回一个指定的默认值
msg: "{{ testvar6 | default('WeiyiGeek',boolean=true) }}"
- debug:
#如果对应的变量未定义,则报出“Mandatory variable not defined.”错误,而不是报出默认错误
msg: "{{ testvar5 | mandatory }}"
END
default过滤器还有一个很方便的用法,不仅能在变量未定义时返回指定的值,还能够让模块的参数变得”可有可无”
- 如果item有mode属性,就把file模块的mode参数的值设置为item的mode属性的值
- 如果item没有mode属性,file模块就直接省略mode参数’omit’的字面意思就是”省略”
实际案例:对应其中一个建立建立的文件进行权限设定,而其他建立的文件则设置为系统缺省权限;1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23# cat >default.yml<<END
- hosts: local
remote_user: root
gather_facts: no
vars:
paths:
- path: /tmp/test
mode: '0444'
- path: /tmp/foo
- path: /tmp/bar
tasks:
#未使用了default过滤器
# - file: dest={{item.path}} state=touch mode={{item.mode}}
# with_items: "{{ paths }}"
# when: item.mode is defined
# - file: dest={{item.path}} state=touch
# with_items: "{{ paths }}"
# when: item.mode is undefined
#使用了default过滤器
- file: dest={{item.path}} state=touch mode={{item.mode | default(omit)}} #我们并没有对文件是否有mode属性进行判断,而是直接调用了file模块的mode参数
with_items: "{{ paths }}"
END
过滤器的用法详细:
json_query 过滤器
描述:如果有时候您从某处API接口进行请求并且成功返回一串json字符串的话,有当您打开后发现里面是杂乱无章的这时可以借助于我们的ansible神器;1
{"logs":[{"domain":"test.com","url":"?key=asdashashdhad&uid=124"},{"domain":"test.com","url":"?key=jioenlkhuxcai&uid=125"}]}
将这段数据所在的文件当做变量文件引入到playbook中,然后输出对应的变量即可;1
2
3
4
5
6
7
8
9
10
- hosts: test70
remote_user: root
gather_facts: no
tasks:
- include_vars:
file: "/testdir/ansible/CDN.log"
name: testjson
- debug:
msg: "{{test.json}}"
运行上面这段脚本后便会将杂乱无章的json格式化显示;
原因:其实json是yaml的子集
,yaml是json的超集
,yaml格式的数据和json格式的数据是可以互相转换
的,所以对于ansible来说,当我们把上例中的json数据文件当做变量文件引入时,就好像引入了一个我们定义好的yaml格式的变量文件一样,对于ansible来说是没有区别的,而且,即使在变量文件中使用yaml格式定义了变量,在使用debug模块输出变量信息时,ansible也会自动将yaml格式的数据转化为json格式后进行输出;
我们把上述json数据转换成yaml的格式,同时列出上述数据的json格式与yaml格式,你可以根据自己的使用习惯选择阅读哪种格式的数据,以便你能够更好的理解这段数据的含义,yaml格式如下:1
2
3
4
5
6
7
8
9
10
11
12#cat >/root/filter.txt<<END
---
logs:
- domainName: test.com
files:
- dateFrom: 2018-09-05-0000
url: ?key=asdashashdhad&uid=124
- domainName: test123.com
files:
- dateFrom: 2018-09-05-0000
url: ?key=asdashashdhad&uid=124
END
此刻如果我们想要获取到整个列表中的所有日志文件的Url,我们该怎么办呢?
答:我们有两种方式一种是通过with_subelements,另外一种是通过json_query的过滤器实现;1
2
3
4
5
6
7
8
9
10
11
12
13
14
15#cat >/root/filterYml.yml<<END
- hosts: local
remote_user: root
gather_facts: no
tasks:
- include_vars:
file: "/root/filter.txt"
name: vartest
- debug:
msg: "{{item.1.url}}"
with_subelements:
- "{{vartest.logs}}"
- files
END
执行结果:(坑呀)1
2
3
4
5
6
7TASK [debug]
ok: [local] => (item=[{u'domainName': u'test.com'}, {u'url': u'?key=asdashashdhad&uid=124', u'dateFrom': u'2018-09-05-0000'}]) => {
"msg": "?key=asdashashdhad&uid=124"
}
ok: [local] => (item=[{u'domainName': u'test123.com'}, {u'url': u'?key=asdashashdhad&uid=124', u'dateFrom': u'2018-09-05-0000'}]) => {
"msg": "?key=asdashashdhad&uid=124"
}
json_query过滤器
描述:可以直接提取json数据,可以进行通配符进行配置,从而比上面采用with_subelement更加的简便;在复现上面的实例的时候我们先来看看你它如何使用;
基础示例:1
2
3
4
5
6
7
8
9
10
11
12
13
14# cat > filter1.txt<<END
---
users:
- name: tom
age: 17
hobby:
- run
- pingpang
- name: jerry
age: 12
hobby:
- computer
- basketball
END
- 当数据结构中存在列表时,我们可以使用\”列表名[*]\”获取到列表下面的所有项
- 使用json_query过滤器对这个变量进行了处理json_query(‘users[*].name’)表示找到users列表中所有元素的name属性
- 使用json_query(‘test.users[?name==`tom`].hobby[*]’)表示只查找users列表中name属性等于tom的hobby信息 (注意是反引号)
- 使用json_query(‘test.users[*].{uname:name,uage:age}’)表示找到users列表中所有用户的name值和age值
1 | #cat >json_queryDemo.yml<<END |
执行结果:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25TASK [json_query Demo 1 : Name]
ok: [local] => {
"msg": ["tom","jerry"]
}
TASK [json_query Demo 2 : Hobby]
ok: [local] => {
"msg": [
["run", "pingpang"],
["computer","basketball"]
]
}
TASK [Advances json_query Demo]
ok: [local] => {
"msg": [["run","pingpang"]] #关键点1 过滤判断是关键
}
TASK [Advances json_query Demo2]
ok: [local] => {
"msg": [
{"userage": 17, "username": "tom"},
{ "userage": 12, "username": "jerry"} #关键点2 指定格式输出
]
}
回归最初的示例:1
2
3
4
5
6
7
8
9
10
11
12
13#cat >json_query.yml<<END
- hosts: local
remote_user: root
gather_facts: no
tasks:
- include_vars:
file: "/root/filter.txt"
name: vartest
- name: "json_query Filter Demo"
debug:
msg: "{{vartest|json_query('logs[*].files[*].url')}}"
END
执行结果:1
2
3
4
5TASK [json_query Filter Demo]
ok: [local] => {
#从这里可以看出于with_subelements关键字的不同更加的高效
"msg": [["?key=asdashashdhad&uid=124"], ["?key=asdashashdhad&uid=124"]]
}
常用过滤器二
描述:继续总结一些使用的过滤器,可以直接采用cmd进行测试:1
2#查看软连接的实际文件(注意硬连接是不行的)
ansible local -m debug -e "path=/bin/bash" -a "msg={{path|realpath}}"
1 |
|
1 | #map过滤器可以从列表中获取到每个元素所共有的某个属性的值,并将这些值组成一个列表 |