ansible:根据原始值将文件中的行替换为新值



使用循环或其他,我看不出如何使用替换或内联模块来实现这一点。

原始文件包含这一行

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
  1. 声明变量
_keys: "{{ goals.keys()|join('') }}"
_match: '^s*goals [{{ _keys }}] + [{{ _keys }}]$'
_group: '^s*goals (.*) + (.*)$'
  1. 在本地
  2. 读取文件
out:
stdout_lines: "{{ lookup('file', '/tmp/replace_goal.txt').splitlines() }}"

或从远程主机

- command: cat /tmp/replace_goal.txt
register: out
  1. 更新文件
- 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 }}"

相关内容

  • 没有找到相关文章

最新更新