使用循环或其他,我看不出如何使用替换或内联模块来实现这一点。
原始文件包含这一行
goals first_goal + second_goal
只我要修改以goals
开头的行(是否有前导空格)
使用这些可能的值:A, B, C, D, E, F
例如
goals C + F
我的角色需要用以下对应替换这一行(第一个字母匹配只是为了简化我的示例):
A -> always
B -> back
C -> car
D -> dance
E -> even
F -> fast
因此,对于本例,转换后的文件将包含以下行:
goals car + fast
(如果可能,选项+:多个单个字母可以产生相同的值,例如A -> always , V -> always, Z -> always
)
这里的东西是自愿有限的,我有更多的价值可能。
最好的方法是什么?谢谢你。
这里有一个解决方案:
给定replace_goal.txt
测试文件
goals A + C
goals F + D
goals B + E
以下剧本:
---
- hosts: localhost
gather_facts: false
vars:
# This is to run from localhost. Replace with correct path on your target
file_dir_path: "{{ playbook_dir }}"
# Mapping of letters to replace with their replacement value
goals:
A: always
B: back
C: car
D: dance
E: even
F: fast
tasks:
- name: Replace goal letters with names
ansible.builtin.replace:
path: "{{ file_dir_path }}/replace_goal.txt"
regexp: '(+? ){{ item.key | regex_escape}}( ?)'
replace: 'g<1>{{ item.value }}g<2>'
loop: "{{ goals | dict2items }}"
给:
PLAY [localhost] ***********************************************************************************************************************************************************************************************************************
TASK [Replace goal letters with names] *************************************************************************************************************************************************************************************************
changed: [localhost] => (item={'key': 'A', 'value': 'always'})
changed: [localhost] => (item={'key': 'B', 'value': 'back'})
changed: [localhost] => (item={'key': 'C', 'value': 'car'})
changed: [localhost] => (item={'key': 'D', 'value': 'dance'})
changed: [localhost] => (item={'key': 'E', 'value': 'even'})
changed: [localhost] => (item={'key': 'F', 'value': 'fast'})
PLAY RECAP *****************************************************************************************************************************************************************************************************************************
localhost : ok=1 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
新的文件内容现在是:
goals always + car
goals fast + dance
goals back + even
给出下面要测试的文件和字典
shell> cat /tmp/replace_goal.txt
first line
goals
goals A + C
goals F + D
goals B + E
goals B
lastline
goals:
A: always
B: back
C: car
D: dance
E: even
F: fast
- 声明变量
_keys: "{{ goals.keys()|join('') }}"
_match: '^s*goals [{{ _keys }}] + [{{ _keys }}]$'
_group: '^s*goals (.*) + (.*)$'
- 在本地 读取文件
out:
stdout_lines: "{{ lookup('file', '/tmp/replace_goal.txt').splitlines() }}"
或从远程主机
- command: cat /tmp/replace_goal.txt
register: out
- 更新文件
- copy:
dest: /tmp/replace_goal.txt
content: |-
{% for line in out.stdout_lines %}
{% if line is regex(_match) %}
{% set p1 = line|regex_search(_group, '\1')|first %}
{% set p2 = line|regex_search(_group, '\2')|first %}
goals {{ goals[p1] }} + {{ goals[p2] }}
{% else %}
{{ line }}
{% endif %}
{% endfor %}
为
TASK [copy] ****************************************************************
--- before: /tmp/replace_goal.txt
+++ after: /home/vlado/.ansible/tmp/ansible-local-5233878lj8lei0/tmpwhajexvl
@@ -1,7 +1,7 @@
first line
goals
-goals A + C
-goals F + D
-goals B + E
+goals always + car
+goals fast + dance
+goals back + even
goals B
lastline
用于测试的完整剧本示例
- hosts: localhost
vars:
goals:
A: always
B: back
C: car
D: dance
E: even
F: fast
out:
stdout_lines: "{{ lookup('file', '/tmp/replace_goal.txt').splitlines() }}"
_keys: "{{ goals.keys()|join('') }}"
_match: '^s*goals [{{ _keys }}] + [{{ _keys }}]$'
_group: '^s*goals (.*) + (.*)$'
tasks:
# - command: cat /tmp/replace_goal.txt
# register: out
- copy:
dest: /tmp/replace_goal.txt
content: |-
{% for line in out.stdout_lines %}
{% if line is regex(_match) %}
{% set p1 = line|regex_search(_group, '\1')|first %}
{% set p2 = line|regex_search(_group, '\2')|first %}
goals {{ goals[p1] }} + {{ goals[p2] }}
{% else %}
{{ line }}
{% endif %}
{% endfor %}
继续使用'replace'模块,我可以丰富您的解决方案Zeitounator,但有一点不能工作:
map现在简化了:goals: A: always D: dance
原文件:goals A+D
regexp'^(s*goalss+){{ item.key | regex_escape}}s*(+*.*)'
replace'1 {{ item.value }} 2'
good result =>goals always +D
现在+
:
原文件后的部分:goals A+D
regexp'^(s*goalss+S+s*+)s*{{ item.key | regex_escape}}(.*)'
相同替换
效果良好=>goals A+ dance
所以,我现在可以使用一个替代,A
将首先匹配,D
就在循环之后:
regexp'^(s*goalss+){{ item.key | regex_escape}}s*(+*.*)|^(s*goalss+S+s*+)s*{{ item.key | regex_escape}}(.*)'
使用原始文件,我得到stdout:changed: [localhost] => (item={'key': 'A', 'value': 'always'}) changed: [localhost] => (item={'key': 'D', 'value': 'dance'})
但结果文件是:dance
?
对我来说,ansible首先构建goals always +D
行,并在第二个循环中将D替换为右边的替换,不是吗?
Ansible似乎不能很好地缓冲第一行替换,当使用正则表达式替换时,但它与2个任务一起工作,每个正则表达式一个:
tasks:
- name: Replace goal left
ansible.builtin.replace:
path: "{{ file_dir_path }}/replace_goal.txt"
regexp: '^(s*goalss+){{ item.key | regex_escape}}s*(+*.*)'
replace: '1 {{ item.value }} 2'
loop: "{{ goals | dict2items }}"
- name: Replace goal right
ansible.builtin.replace:
path: "{{ file_dir_path }}/replace_goal.txt"
regexp: '^(s*goalss+S+s*+)s*{{ item.key | regex_escape}}(.*)'
replace: '1 {{ item.value }} 2'
loop: "{{ goals | dict2items }}"