英文:
Replace string in file, if exists with Ansible playbook
问题
我有一个文件,其中包含一个由多个空格分隔的字符串组成的单行:
```shell
$ cat /tmp/strings.txt
alpha beta gamma zeta omega
我的目标是检查 /tmp/strings.txt
中是否不存在字符串 delta
,如果不存在,则在 gamma
字符串后面添加它:
$ cat /tmp/strings.txt
alpha beta gamma delta zeta omega
我认为以下解决方案可能是合适的:
- name: 检查是否存在 delta 字符串
ansible.builtin.command: grep 'delta' /tmp/strings.txt | wc -l
register: delta_string
- name: 添加 delta 字符串
ansible.builtin.blockinfile:
block: gamma delta
path: /tmp/strings.txt
when: delta_string.stdout == 0
这是否是 Ansible 中适当使用字符串替换的方式?不确定 ansible.builtin.blockinfile
块如何工作,它会在未找到时将 gamma delta
字符串插入文件中作为 gamma
的替换,还是将其添加到文件末尾?是否有一个不需要 when
检查的解决方案?
<details>
<summary>英文:</summary>
I have a file, containing a single line of multiple space separated strings:
```shell
$ cat /tmp/strings.txt
alpha beta gamma zeta omega
My goal is to check if delta
string is not present inside /tmp/strings.txt, and if not, add it after gamma
string:
$ cat /tmp/strings.txt
alpha beta gamma delta zeta omega
What I think would be a solution:
- name: Check if delta string is present
ansible.builtin.command: grep 'delta' /tmp/strings.txt | wc -l
register: delta_string
- name: Add delta string
ansible.builtin.blockinfile:
block: gamma delta
path: /tmp/strings.txt
when: delta_string.stdout == 0
Is this a proper use of string replacements in Ansible? Not sure how ansible.builtin.blockinfile
block works, will it insert the gamma delta
string if is not found, as replacement for gamma
, or will it add it at the end of file?
Is there a solution which does require a when
check?
答案1
得分: 1
将双胞胎放入字典中,例如:
twins:
gamma: delta
foo: bar
读取文件并拆分项目。声明变量
strings: "{{ out.content|b64decode|split() }}"
以下任务
- slurp:
src: /tmp/strings.txt
register: out
给出字符串列表
strings: [alpha, beta, gamma, zeta, omega]
迭代 strings 并添加缺失的双胞胎
update_str: |
[
{% for i in strings %}
{% if i in twins and strings[loop.index]|d(None) != twins[i] %}
{{ i }}, {{ twins[i] }},
{% else %}
{{ i }},
{% endif %}
{% endfor %}
]
给出有效的YAML
update_str: |-
[
alpha,
beta,
gamma, delta,
zeta,
omega,
]
将字符串转换为列表
update: "{{ update_str|from_yaml }}"
给出
update: [alpha, beta, gamma, delta, zeta, omega]
连接项目并写入文件
- copy:
dest: /tmp/strings.txt
content: "{{ update|join(' ') }}"
给出
shell> cat /tmp/strings.txt
alpha beta gamma delta zeta omega
用于测试的完整playbook示例
- hosts: localhost
vars:
twins:
gamma: delta
foo: bar
strings: "{{ out.content|b64decode|split() }}"
update_str: |
[
{% for i in strings %}
{% if i in twins and strings[loop.index]|d(None) != twins[i] %}
{{ i }}, {{ twins[i] }},
{% else %}
{{ i }},
{% endif %}
{% endfor %}
]
update: "{{ update_str|from_yaml }}"
tasks:
- slurp:
src: /tmp/strings.txt
register: out
- debug:
var: strings
- debug:
var: update_str
- debug:
var: update
- copy:
dest: /tmp/strings.txt
content: "{{ update|join(' ') }}"
英文:
Put the twins into a dictionary, e.g.
twins:
gamma: delta
foo: bar
Read the file and split the items. Declare the variable
strings: "{{ out.content|b64decode|split() }}"
The task below
- slurp:
src: /tmp/strings.txt
register: out
gives the list of the strings
strings: [alpha, beta, gamma, zeta, omega]
Iterate strings and add the twins if missing
update_str: |
[
{% for i in strings %}
{% if i in twins and strings[loop.index]|d(None) != twins[i] %}
{{ i }}, {{ twins[i] }},
{% else %}
{{ i }},
{% endif %}
{% endfor %}
]
gives valid YAML
update_str: |-
[
alpha,
beta,
gamma, delta,
zeta,
omega,
]
Convert the string to the list
update: "{{ update_str|from_yaml }}"
gives
update: [alpha, beta, gamma, delta, zeta, omega]
Join the items and write the file
- copy:
dest: /tmp/strings.txt
content: "{{ update|join(' ') }}"
gives
shell> cat /tmp/strings.txt
alpha beta gamma delta zeta omega
<hr>
<sup>
Example of a complete playbook for testing
- hosts: localhost
vars:
twins:
gamma: delta
foo: bar
strings: "{{ out.content|b64decode|split() }}"
update_str: |
[
{% for i in strings %}
{% if i in twins and strings[loop.index]|d(None) != twins[i] %}
{{ i }}, {{ twins[i] }},
{% else %}
{{ i }},
{% endif %}
{% endfor %}
]
update: "{{ update_str|from_yaml }}"
tasks:
- slurp:
src: /tmp/strings.txt
register: out
- debug:
var: strings
- debug:
var: update_str
- debug:
var: update
- copy:
dest: /tmp/strings.txt
content: "{{ update|join(' ') }}"
</sup>
答案2
得分: 0
根据您的描述,我理解您希望有一个仅包含“text”一行的文件。
由于Ansible是一种配置管理工具,您只需要声明所需的状态即可。无需进行任何检查,如果满足条件则插入(否则)的构造。
对于输入文件
~/test$ cat strings.txt
alpha beta gamma zeta omega
一个最小的示例playbook如下:
---
- hosts: localhost
become: false
gather_facts: false
tasks:
- name: 确保lineinfile处于所需状态
lineinfile:
path: strings.txt
line: alpha beta gamma delta zeta omega
regexp: '^alpha' # 或者甚至 '^alpha beta gamma zeta omega'
将会生成一个输出文件
~/test$ cat strings.txt
alpha beta gamma delta zeta omega
更多文档
lineinfile
模块 – 管理文本文件中的行
此模块确保文件中有特定的行,或替换现有行...
也有可能会奏效
英文:
From your description I understand that you like to have a file with a single line of "text" only.
Since Ansible is a Configuration Management Tool with which you declare the Desired State, that is all what you would need to do. There is no need for any CHECK IF THEN INSERT (ELSE) WHEN contruct.
For an input file of
~/test$ cat strings.txt
alpha beta gamma zeta omega
a minimal example playbook
---
- hosts: localhost
become: false
gather_facts: false
tasks:
- name: Make sure lineinfile is in Desired State
lineinfile:
path: strings.txt
line: alpha beta gamma delta zeta omega
regexp: '^alpha' # or even '^alpha beta gamma zeta omega'
will result into an output file
~/test$ cat strings.txt
alpha beta gamma delta zeta omega
Further Documentation
lineinfile
module – Manage lines in text files
> This module ensures a particular line is in a file, or replace an existing line ...
Most likely would work too
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论