使用insertafter复制Ansible Lineinfile

时间:2018-11-18 05:09:33

标签: regex ansible jinja2

我正在尝试使用ansibles /etc/hosts将一个条目添加到我的lineinfile文件中。我希望逻辑是如果找到条目127.0.0.1 mysite.local,然后什么也不做,否则将其插入行127.0.1.1

之后
127.0.0.1   localhost
127.0.1.1   mypc
127.0.0.1      mysite.local

部分工作后我有插入物,但似乎实际的正则表达式搜索未能找到现有条目,因此我不断重复插入127.0.0.1 mysite.local

文档确实会说;

  

在修改一行时,正则表达式通常应匹配该行的初始状态以及被行替换后的状态,以确保幂等。

但是我不确定这对我的正则表达式如何适用。目前我的扮演是;

- name: Add the site to hosts
  lineinfile:
    path: /etc/hosts
    # Escape special chars
    regex: "^{{ domain|regex_escape() }}"
    line: "127.0.0.1      {{ domain }}"
    insertafter: '127\.0\.1\.1'
    firstmatch: yes
  become: yes

其中domainmysite.local

我已经查看了this的答案,但是我很确定我不能使用backrefs,因为文档说明了这一点;

  

该标志会稍微改变模块的操作; insertbefore和insertafter将被忽略,并且如果regexp与文件中的任何地方都不匹配,则文件将保持不变。

我已经尝试过了

regex: '127\.0\.0\.1\s+?{{ domain|regex_escape() }}'

也没有运气

3 个答案:

答案 0 :(得分:1)

根据this link,lineinfile扫描文件并一次应用正则表达式一行,这意味着您不能使用可浏览整个文件的正则表达式。我不熟悉lineinfile工具,但是如果可以使用上面链接中使用的“替换”工具,则可以根据需要使用以下Python正则表达式进行匹配:

\A((?:(?!127\.0\.0\.1\s)[\s\S])*?)(?:\Z|127\.0\.0\.1\s+(?!{{ domain|regex_escape() }})\S+\n|(127\.0\.1\.1\s+\S+(?![\s\S]*\n127\.0\.0\.1\s)\n))

替换为:“ \ 1 \ 2127.0.0.1 {{域}} \ n”

非捕获组处理三种不同的情况:

  1. Case 1:127.0.1.1和127.0.0.1不存在,因此请在末尾插入
  2. Case 2:127.0.0.1与其他主机一起存在,因此请替换条目
  3. Case 3:存在127.0.1.1,因此请在其后插入

第二种情况是通过避免匹配“ 127.0.0.1”条目(如果已经存在)来解决幂等问题。

答案 1 :(得分:1)

似乎firstmatch: yes在破坏事物。它适用于以下任务(我用花哨的标签替换了空格,但空格也起作用):

  - name: Add the site to hosts
    lineinfile:
      path: /etc/hosts
      # Escape special chars
      regexp: "{{ domain|regex_escape() }}"
      line: "127.0.0.1{{ '\t' }}{{ domain }}"
      insertafter: '127\.0\.1\.1'

答案 2 :(得分:0)

doc说:

  

insertafter:...如果将正则表达式同时传递给regexp和insertafter,则仅在找不到与regexp匹配的情况下才使用insertafter。

任务中的正则表达式扩展为

regex: ^mysite\.local

找不到此正则表达式,因为没有以“ mysite.local”开头的行。因此, insertafter 被接受,并且在 127.0.1.1 之后插入“行”。