insert files lines into another depending regex filter in Ansible

Question:

I would copy lines from a file /tmp/test1 to a file /tmp/test2
the /tmp/test1 contains:

+ : argument1 : ALL
+ : argument2 : ALL
+ : @test1 : ALL
+ : @test2 : ALL
+ : @test3 : ALL

the /tmp/test2 contains:

+ : argument1.1 : ALL
+ : argument2192 : ALL
+ : @example : ALL
+ : @test2 : ALL
+ : @example1 : ALL

So my main goal is to insert every line that doesn’t exist in /tmp/test2 from file /tmp/test1
and that the line added must be added at the end of the last line which is containing the same beginning after + : : ^[[:alpha:]] and ^@, so /tmp/test2 should look like this:

+ : argument1.1  : ALL
+ : argument2192 : ALL
+ : argument1 : ALL
+ : argument2 : ALL
+ : @example : ALL
+ : @test2 : ALL
+ : @example1 : ALL
+ : @test1 : ALL
+ : @test3 : ALL

I got a reply about how to merge the 2 files from this answer Vladimir Botka_answer. But what is causing an issue for me is the : + : at the begining of each <line>, the filter must be applied after that if it starts with @ or alpha

Asked By: medisamm

||

Answers:

Put prefix and regex into variables and test the first 5 characters. For example,

    - name: insert line
      lineinfile:
        path: /tmp/test2
        line: "{{ item }}"
        insertafter: "{{ (item[0:5] == prefix)|ternary('EOF', omit) }}"
        insertbefore: "{{ (item[0:5] != prefix)|ternary(regex, omit) }}"
        firstmatch: true
      loop: "{{ tmp_content.stdout_lines }}"
      vars:
        prefix: '+ : @'
        regex: '^+ : @.*$'

gives

shell> cat /tmp/test2
+ : argument1.1 : ALL
+ : argument2192 : ALL
+ : argument1 : ALL
+ : argument2 : ALL
+ : @example : ALL
+ : @test2 : ALL
+ : @example1 : ALL
+ : @test1 : ALL
+ : @test3 : ALL

  • Example of a complete playbook for testing
- hosts: localhost
  tasks:
    - name: check test1 content
      command: cat /tmp/test1
      register: tmp_content
      changed_when: false
    - name: insert line
      lineinfile:
        path: /tmp/test2
        line: "{{ item }}"
        insertafter: "{{ (item[0:5] == prefix)|ternary('EOF', omit) }}"
        insertbefore: "{{ (item[0:5] != prefix)|ternary(regex, omit) }}"
        firstmatch: true
      loop: "{{ tmp_content.stdout_lines }}"
      vars:
        prefix: '+ : @'
        regex: '^+ : @.*$'
  • The playbook is idempotent. See the output of the diff_mode below
shell> ansible-playbook pb.yml --diff
...
TASK [insert line] ****************************************
--- before: /tmp/test2 (content)
+++ after: /tmp/test2 (content)
@@ -1,5 +1,6 @@
 + : argument1.1 : ALL
 + : argument2192 : ALL
++ : argument1 : ALL
 + : @example : ALL
 + : @test2 : ALL
 + : @example1 : ALL

changed: [localhost] => (item=+ : argument1 : ALL)
--- before: /tmp/test2 (content)
+++ after: /tmp/test2 (content)
@@ -1,6 +1,7 @@
 + : argument1.1 : ALL
 + : argument2192 : ALL
 + : argument1 : ALL
++ : argument2 : ALL
 + : @example : ALL
 + : @test2 : ALL
 + : @example1 : ALL

changed: [localhost] => (item=+ : argument2 : ALL)
--- before: /tmp/test2 (content)
+++ after: /tmp/test2 (content)
@@ -5,3 +5,4 @@
 + : @example : ALL
 + : @test2 : ALL
 + : @example1 : ALL
++ : @test1 : ALL

changed: [localhost] => (item=+ : @test1 : ALL)
ok: [localhost] => (item=+ : @test2 : ALL)
--- before: /tmp/test2 (content)
+++ after: /tmp/test2 (content)
@@ -6,3 +6,4 @@
 + : @test2 : ALL
 + : @example1 : ALL
 + : @test1 : ALL
++ : @test3 : ALL

changed: [localhost] => (item=+ : @test3 : ALL)

Q: " Add the lines containing @ behind the last match line containing @."

A: Use regex both in insertafter and insertbefore, and select firstmatch according the prefix. Technically, append @ lines to the @ block and prepend others. For example, given the file

shell> cat /tmp/test2
+ : argument1.1 : ALL
+ : argument2192 : ALL
+ : @example : ALL
+ : @test2 : ALL
+ : @example1 : ALL
+ : <rubish>

The task below does the job

    - name: insert line
      lineinfile:
        path: /tmp/test2
        line: "{{ item }}"
        insertafter: "{{ (item[0:5] == prefix)|ternary(regex, omit) }}"
        insertbefore: "{{ (item[0:5] != prefix)|ternary(regex, omit) }}"
        firstmatch: "{{ (item[0:5] != prefix)|ternary(true, false) }}"
      loop: "{{ tmp_content.stdout_lines }}"
      vars:
        prefix: '+ : @'
        regex: '^+ : @.*$'

See the output of the diff_mode below

shell> ansible-playbook pb.yml --diff
...
TASK [insert line] ******************************************
--- before: /tmp/test2 (content)
+++ after: /tmp/test2 (content)
@@ -1,5 +1,6 @@
 + : argument1.1 : ALL
 + : argument2192 : ALL
++ : argument1 : ALL
 + : @example : ALL
 + : @test2 : ALL
 + : @example1 : ALL

changed: [localhost] => (item=+ : argument1 : ALL)
--- before: /tmp/test2 (content)
+++ after: /tmp/test2 (content)
@@ -1,6 +1,7 @@
 + : argument1.1 : ALL
 + : argument2192 : ALL
 + : argument1 : ALL
++ : argument2 : ALL
 + : @example : ALL
 + : @test2 : ALL
 + : @example1 : ALL

changed: [localhost] => (item=+ : argument2 : ALL)
--- before: /tmp/test2 (content)
+++ after: /tmp/test2 (content)
@@ -5,4 +5,5 @@
 + : @example : ALL
 + : @test2 : ALL
 + : @example1 : ALL
++ : @test1 : ALL
 + : <rubish>

changed: [localhost] => (item=+ : @test1 : ALL)
ok: [localhost] => (item=+ : @test2 : ALL)
--- before: /tmp/test2 (content)
+++ after: /tmp/test2 (content)
@@ -6,4 +6,5 @@
 + : @test2 : ALL
 + : @example1 : ALL
 + : @test1 : ALL
++ : @test3 : ALL
 + : <rubish>

changed: [localhost] => (item=+ : @test3 : ALL)

Answered By: Vladimir Botka
Categories: questions Tags: , , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.