断言模块:如果只找到一次字符串,是否有可能失败?
assert module: Is it possible to fail if string is found only once?
我正在解析 Windows 系统(使用 winrm)上的文本文件的一些输出。如果它没有多次看到 'test' 这个词,我试图让剧本失败。
如果它至少看到一次 'test' 这个词,这就是我所拥有的,仅用于继续剧本:
- name: "Windows Output | Parse file"
win_shell: |
(Get-Content C:\TEST\output.txt)
register: 'testing_parse'
- name: "File output | verification"
assert:
that:
- "'test' in testing_parse.stdout"
fail_msg: "Exiting now."
success_msg: "Proceeding with task."
我认为下面的方法行得通,但行不通:
- name: "File output | verification"
assert:
that:
- "'test' in testing_parse.stdout >= '2'"
fail_msg: "Exiting now."
success_msg: "Proceeding with task."
如何修复我的 assert
任务,使其满足我的要求?
TL;DR
- name: "File output | verification"
vars:
watch_regex: '(?:^|\W)(test)(?:$|\W)'
assert:
that:
- testing_parse.stdout | regex_findall(watch_regex) | length > 1
fail_msg: "Exiting now."
success_msg: "Proceeding with task."
为什么 in
测试不合适
in
return 一个布尔值
让我们先看看我们在几种情况下从 in
测试中得到了什么
$ ansible localhost -m debug -a "msg={{ 'test' in my_test }}" \
-e "my_test='a test'"
localhost | SUCCESS => {
"msg": true
}
$ ansible localhost -m debug -a "msg={{ 'test' in my_test }}" \
-e "my_test='a test and an other test'"
localhost | SUCCESS => {
"msg": true
}
$ ansible localhost -m debug -a "msg={{ 'test' in my_test }}" \
-e "my_test='no word we look for'"
localhost | SUCCESS => {
"msg": false
}
如您所见,它始终 return 一个布尔值,具体取决于大海捞针中是否存在针。
in
没有找到字
还要注意 in
不是很擅长找词(因为你提到过),如下所示:
# It will match a substring in a middle of an other word
$ ansible localhost -m debug -a "msg={{ 'test' in my_test }}" \
-e my_test="blahtesttoto"
localhost | SUCCESS => {
"msg": true
}
# It will not match a word inside an element of a list...
$ ansible localhost -m debug -a "msg={{ 'test' in my_test }}" \
-e '{"my_test":["this is", "a test"]}'
localhost | SUCCESS => {
"msg": false
}
# ... but only an exact match of an element of a list
$ ansible localhost -m debug -a "msg={{ 'test' in my_test }}" \
-e '{"my_test":["a", "test"]}'
localhost | SUCCESS => {
"msg": true
}
反正你的表达方式不对
最后,让我们看看你写表达式时的尝试:
'test' in testing_parse.stdout >= '2'
这意味着:
- 检查字符串
testing_parse.stdout
在词法上是否优于或等于字符串 '2'
.
- 现在检查是否在前面的布尔结果中找到字符串
'test'
。
正如您现在可以根据解释猜测的那样,这绝对不可能 return true
.
regex_findall
救援
查找特定单词的一种方法是使用正则表达式。下面将查找 test
单词,即 "test"
字符串前后跟任何非单词字符(行尾、行首、白色 space、制表符、标点符号.. ..).
(?:^|\W)(test)(?:$|\W)
如果您不熟悉正则表达式,请参阅 this answer for a specific explanation and https://www.regextutorial.org/ 获取一般资源(我不是附属的,您可以使用您喜欢的搜索引擎找到其他人)。
regex_find_all
filter 可以 return 将正则表达式与字符串的所有匹配项放入列表中
$ ansible localhost -m debug \
-a "msg={{ my_test | regex_findall('(?:^|\W)(test)(?:$|\W)') }}" \
-e "my_test='test'"
localhost | SUCCESS => {
"msg": [
"test"
]
}
$ ansible localhost -m debug \
-a "msg={{ my_test | regex_findall('(?:^|\W)(test)(?:$|\W)') }}" \
-e "my_test='test and an other test but not blahtesttoto yet test'"
localhost | SUCCESS => {
"msg": [
"test",
"test",
"test"
]
}
$ ansible localhost -m debug \
-a "msg={{ my_test | regex_findall('(?:^|\W)(test)(?:$|\W)') }}" \
-e "my_test='notest'"
localhost | SUCCESS => {
"msg": []
}
一旦我们有了它,我们只需要计算 returned 列表中带有 length
过滤器的元素数。
$ ansible localhost -m debug \
-a "msg={{ my_test | regex_findall('(?:^|\W)(test)(?:$|\W)') | length }}" \
-e "my_test='test and an other test but not blahtesttoto yet test'"
localhost | SUCCESS => {
"msg": "3"
}
最后我们可以根据您的要求修复您的 assert
任务:
- name: "File output | verification"
vars:
watch_regex: '(?:^|\W)(test)(?:$|\W)'
assert:
that:
- testing_parse.stdout | regex_findall(watch_regex) | length > 1
fail_msg: "Exiting now."
success_msg: "Proceeding with task."
我正在解析 Windows 系统(使用 winrm)上的文本文件的一些输出。如果它没有多次看到 'test' 这个词,我试图让剧本失败。
如果它至少看到一次 'test' 这个词,这就是我所拥有的,仅用于继续剧本:
- name: "Windows Output | Parse file"
win_shell: |
(Get-Content C:\TEST\output.txt)
register: 'testing_parse'
- name: "File output | verification"
assert:
that:
- "'test' in testing_parse.stdout"
fail_msg: "Exiting now."
success_msg: "Proceeding with task."
我认为下面的方法行得通,但行不通:
- name: "File output | verification"
assert:
that:
- "'test' in testing_parse.stdout >= '2'"
fail_msg: "Exiting now."
success_msg: "Proceeding with task."
如何修复我的 assert
任务,使其满足我的要求?
TL;DR
- name: "File output | verification"
vars:
watch_regex: '(?:^|\W)(test)(?:$|\W)'
assert:
that:
- testing_parse.stdout | regex_findall(watch_regex) | length > 1
fail_msg: "Exiting now."
success_msg: "Proceeding with task."
为什么 in
测试不合适
in
return 一个布尔值
让我们先看看我们在几种情况下从 in
测试中得到了什么
$ ansible localhost -m debug -a "msg={{ 'test' in my_test }}" \
-e "my_test='a test'"
localhost | SUCCESS => {
"msg": true
}
$ ansible localhost -m debug -a "msg={{ 'test' in my_test }}" \
-e "my_test='a test and an other test'"
localhost | SUCCESS => {
"msg": true
}
$ ansible localhost -m debug -a "msg={{ 'test' in my_test }}" \
-e "my_test='no word we look for'"
localhost | SUCCESS => {
"msg": false
}
如您所见,它始终 return 一个布尔值,具体取决于大海捞针中是否存在针。
in
没有找到字
还要注意 in
不是很擅长找词(因为你提到过),如下所示:
# It will match a substring in a middle of an other word
$ ansible localhost -m debug -a "msg={{ 'test' in my_test }}" \
-e my_test="blahtesttoto"
localhost | SUCCESS => {
"msg": true
}
# It will not match a word inside an element of a list...
$ ansible localhost -m debug -a "msg={{ 'test' in my_test }}" \
-e '{"my_test":["this is", "a test"]}'
localhost | SUCCESS => {
"msg": false
}
# ... but only an exact match of an element of a list
$ ansible localhost -m debug -a "msg={{ 'test' in my_test }}" \
-e '{"my_test":["a", "test"]}'
localhost | SUCCESS => {
"msg": true
}
反正你的表达方式不对
最后,让我们看看你写表达式时的尝试:
'test' in testing_parse.stdout >= '2'
这意味着:
- 检查字符串
testing_parse.stdout
在词法上是否优于或等于字符串'2'
. - 现在检查是否在前面的布尔结果中找到字符串
'test'
。
正如您现在可以根据解释猜测的那样,这绝对不可能 return true
.
regex_findall
救援
查找特定单词的一种方法是使用正则表达式。下面将查找 test
单词,即 "test"
字符串前后跟任何非单词字符(行尾、行首、白色 space、制表符、标点符号.. ..).
(?:^|\W)(test)(?:$|\W)
如果您不熟悉正则表达式,请参阅 this answer for a specific explanation and https://www.regextutorial.org/ 获取一般资源(我不是附属的,您可以使用您喜欢的搜索引擎找到其他人)。
regex_find_all
filter 可以 return 将正则表达式与字符串的所有匹配项放入列表中
$ ansible localhost -m debug \
-a "msg={{ my_test | regex_findall('(?:^|\W)(test)(?:$|\W)') }}" \
-e "my_test='test'"
localhost | SUCCESS => {
"msg": [
"test"
]
}
$ ansible localhost -m debug \
-a "msg={{ my_test | regex_findall('(?:^|\W)(test)(?:$|\W)') }}" \
-e "my_test='test and an other test but not blahtesttoto yet test'"
localhost | SUCCESS => {
"msg": [
"test",
"test",
"test"
]
}
$ ansible localhost -m debug \
-a "msg={{ my_test | regex_findall('(?:^|\W)(test)(?:$|\W)') }}" \
-e "my_test='notest'"
localhost | SUCCESS => {
"msg": []
}
一旦我们有了它,我们只需要计算 returned 列表中带有 length
过滤器的元素数。
$ ansible localhost -m debug \
-a "msg={{ my_test | regex_findall('(?:^|\W)(test)(?:$|\W)') | length }}" \
-e "my_test='test and an other test but not blahtesttoto yet test'"
localhost | SUCCESS => {
"msg": "3"
}
最后我们可以根据您的要求修复您的 assert
任务:
- name: "File output | verification"
vars:
watch_regex: '(?:^|\W)(test)(?:$|\W)'
assert:
that:
- testing_parse.stdout | regex_findall(watch_regex) | length > 1
fail_msg: "Exiting now."
success_msg: "Proceeding with task."