Ansible 替换正则表达式前后的多行

ansible replace multiples lines before and after regexp

提问人:Carvainth 提问时间:10/10/2023 最后编辑:Carvainth 更新时间:10/11/2023 访问量:71

问:

我正在使用 ansible tower 修改文件 .baroc,使用用户为正则表达式提交的变量。

对于exampe,这是要修改的文件:

AUTOMATION;
groupe_affectation='Test'';
msg_exception='APPLI 1';
mc_long_msg='eKBX';
commentaire='Automatic';
END

AUTOMATION;
groupe_affectation='Test'';
msg_exception='APPLI 1';
mc_long_msg='eKB42';
commentaire='Automatic';
END

AUTOMATION;
mc_service='.\* - PRE-PRODUCTION';
application_infogerant='toto|test';
mc_long_msg='eKB12345';
mc_host='';
mc_object_class='';
mc_object='';
mc_parameter='';
msg='';
groupe_affectation='EXPLOITATION_APPLICATIONS-TOTO';
commentaire='DT123';
END

\########################################################################################################################################################################

# TOTO - Affectation CA

\########################################################################################################################################################################

# TOTO - CTRLM

AUTOMATION;
mc_long_msg='eKB007';
ctm_application='test.';
ctm_group='';
ctm_jobname='';
ctm_datacenter='';
ctm_nodeid='';
ctm_msg='';
groupe_affectation='MCO_test';
commentaire='DT01';
END
AUTOMATION;
groupe_affectation='SUPPORT';
msg_exception='APPLI 4';
mc_long_msg='eKB007';
commentaire='Automatic';
END

在这个问题上,我想删除整个集团:

AUTOMATION;
groupe_affectation='Test'';
msg_exception='APPLI 1';
mc_long_msg='eKB42';
commentaire='Automatic';
END

这是我的剧本:

---

- name: Suppression d'un eKB au fichier Paperboy
  hosts: localhost
  become: yes

  tasks:

  - name: Vérifier si le eKB est bien présent ########Check if the eKB is present
    lineinfile:
    path: /exemple/of/a/PATH.baroc
    line: "eKB042"
    state: absent
    check_mode: yes
    register: presence

  - name: Arrêter le playbook si le eKB n'est pas présent ########Stop the playbook if the eKB is absent
    fail:
    msg: "L'eKB042 n'est pas présent dans le fichier baroc."
    when: presence.changed

  - name: Copie du fichier baroc dans le old #Backup
    ansible.builtin.copy:
    src: /exemple/of/a/PATH.baroc
    dest: /exemple/of/an/old/PATH.baroc.soway.{{ ansible_date_time.iso8601_basic }}

  - name: Suppression de la règle au fichier PAPERBOY.baroc ########Delete bloc
    ansible.builtin.replace:
    path: /exemple/of/a/PATH.baroc
    after: 'PAPERBOY(?:(?!PAPERBOY)(.|\\n))*eKB0031549'
    before: 'END(?!(.|\\n)eKB0031549)'
    regexp: '^.*(eKB042).$'
    replace: '! '
    ...

问题是它开始了最后一次品尝而没有结束...... 我知道最后一个任务之前的所有内容都可以正常工作,因为我将其用于其他目的(添加行以制作新的 eKB),并且它工作正常。我认为问题出在我使用的正则表达式上......即使在 regex101 上也没关系。

因此,我愿意将集团从 AUTOMATION 删除到 END(我认为是最佳实践),或者如果太困难,请删除 eKB 之前的 3 行和 eKB 之后的 2 行;因为 playbook 将始终用于删除类似的自动化块。较长的块不会以这种方式删除,也不会具有相同的 eKB 编号

感谢您的帮助

正则表达式 ansible 正则表达式替换 ansible-awx

评论


答:

1赞 Vladimir Botka 10/10/2023 #1

给定文件

shell> cat PATH.baroc 
AUTOMATION;
groupe_affectation='Test'';
msg_exception='APPLI 1';
mc_long_msg='eKBX';
commentaire='Automatic';
END

PAPERBOY;
groupe_affectation='Test'';
msg_exception='APPLI 1';
mc_long_msg='eKB42';
commentaire='Automatic';
END

AUTOMATION;
mc_service='.\* - PRE-PRODUCTION';
application_infogerant='toto|test';
mc_long_msg='eKB12345';
mc_host='';
mc_object_class='';
mc_object='';
mc_parameter='';
msg='';
groupe_affectation='EXPLOITATION_APPLICATIONS-TOTO';
commentaire='DT123';
END

\########################################################################################################################################################################

# TOTO - Affectation CA

\########################################################################################################################################################################

# TOTO - CTRLM

AUTOMATION;
mc_long_msg='eKB007';
ctm_application='test.';
ctm_group='';
ctm_jobname='';
ctm_datacenter='';
ctm_nodeid='';
ctm_msg='';
groupe_affectation='MCO_test';
commentaire='DT01';
END
AUTOMATION;
groupe_affectation='SUPPORT';
msg_exception='APPLI 4';
mc_long_msg='eKB007';
commentaire='Automatic';
END

Q: Delete the entire bloc

PAPERBOY;
groupe_affectation='Test'';
msg_exception='APPLI 1';
mc_long_msg='eKB42';
commentaire='Automatic';
END

A: Read the file

    - shell: cat PATH.baroc | egrep '.*;|END'
      register: out

and parse the content

  test: "{{ out.stdout|
            split('END')|
            select|
            map('trim')|
            map('regex_replace', ';', '')|
            map('community.general.jc', 'ini') }}"

gives

  test:
  - AUTOMATION: ''
    commentaire: Automatic
    groupe_affectation: Test'
    mc_long_msg: eKBX
    msg_exception: APPLI 1
  - PAPERBOY: ''
    commentaire: Automatic
    groupe_affectation: Test'
    mc_long_msg: eKB42
    msg_exception: APPLI 1
  - AUTOMATION: ''
    application_infogerant: toto|test
    commentaire: DT123
    groupe_affectation: EXPLOITATION_APPLICATIONS-TOTO
    mc_host: ''
    mc_long_msg: eKB12345
    mc_object: ''
    mc_object_class: ''
    mc_parameter: ''
    mc_service: .\* - PRE-PRODUCTION
    msg: ''
  - AUTOMATION: ''
    commentaire: DT01
    ctm_application: test.
    ctm_datacenter: ''
    ctm_group: ''
    ctm_jobname: ''
    ctm_msg: ''
    ctm_nodeid: ''
    groupe_affectation: MCO_test
    mc_long_msg: eKB007
  - AUTOMATION: ''
    commentaire: Automatic
    groupe_affectation: SUPPORT
    mc_long_msg: eKB007
    msg_exception: APPLI 4

Modify what you want and write the block

    - debug:
        msg: |
          {% for i in test|reject('contains', 'PAPERBOY') %}
          {% for k,v in i.items() %}
          {% if loop.index == 1 %}
          {{ k }};
          {% else %}
          {{ k }}='{{ v }}';
          {% endif %}
          {% endfor %}
          END

          {% endfor %}

gives

    AUTOMATION;
    groupe_affectation='Test'';
    msg_exception='APPLI 1';
    mc_long_msg='eKBX';
    commentaire='Automatic';
    END
  
    AUTOMATION;
    mc_service='.\* - PRE-PRODUCTION';
    application_infogerant='toto|test';
    mc_long_msg='eKB12345';
    mc_host='';
    mc_object_class='';
    mc_object='';
    mc_parameter='';
    msg='';
    groupe_affectation='EXPLOITATION_APPLICATIONS-TOTO';
    commentaire='DT123';
    END
  
    AUTOMATION;
    mc_long_msg='eKB007';
    ctm_application='test.';
    ctm_group='';
    ctm_jobname='';
    ctm_datacenter='';
    ctm_nodeid='';
    ctm_msg='';
    groupe_affectation='MCO_test';
    commentaire='DT01';
    END
  
    AUTOMATION;
    groupe_affectation='SUPPORT';
    msg_exception='APPLI 4';
    mc_long_msg='eKB007';
    commentaire='Automatic';
    END

Example of a complete playbook for testing

- hosts: localhost

  vars:

    test: "{{ out.stdout|
              split('END')|
              select|
              map('trim')|
              map('regex_replace', ';', '')|
              map('community.general.jc', 'ini') }}"

  tasks:

    - shell: cat PATH.baroc | egrep '.*;|END'
      register: out

    - debug:
        var: test

    - debug:
        msg: |
          {% for i in test|reject('contains', 'PAPERBOY') %}
          {% for k,v in i.items() %}
          {% if loop.index == 1 %}
          {{ k }};
          {% else %}
          {{ k }}='{{ v }}';
          {% endif %}
          {% endfor %}
          END

          {% endfor %}

    - copy:
        dest: test.ini
        content: |
          {% for i in test|reject('contains', 'PAPERBOY') %}
          {% for k,v in i.items() %}
          {% if loop.index == 1 %}
          {{ k }};
          {% else %}
          {{ k }}='{{ v }}';
          {% endif %}
          {% endfor %}
          END

          {% endfor %}

Q: Delete the entire bloc

AUTOMATION;
groupe_affectation='Test'';
msg_exception='APPLI 1';
mc_long_msg='eKBX';
commentaire='Automatic';
END

A: Put the blocks you want to delete into a list

    blocks_del:
      - |
        AUTOMATION;
        groupe_affectation='Test'';
        msg_exception='APPLI 1';
        mc_long_msg='eKBX';
        commentaire='Automatic';
        END

Convert the blocks to lines

    lines_del: "{{ blocks_del|map('split')|map('join', ' ') }}"

    lines: |
      {% filter from_yaml %}
      {% for i in test %}
      {% for k,v in i.items() %}
      {% if loop.index == 1 %}
      - {{ k }};
      {% else %}
        {{ k }}='{{ v }}';
      {% endif %}
      {% endfor %}
        END
      {% endfor %}
      {% endfilter %}

and write the difference between the lists

    - debug:
        msg: |
          {% for i in lines|difference(lines_del) %}
          {% for j in i|split('; ') %}
          {{ j }}{% if not loop.last %};{% endif +%}
          {% endfor %}

          {% endfor %}

gives

  msg: |-
    PAPERBOY;
    groupe_affectation='Test'';
    msg_exception='APPLI 1';
    mc_long_msg='eKB42';
    commentaire='Automatic';
    END
  
    AUTOMATION;
    mc_service='.\* - PRE-PRODUCTION';
    application_infogerant='toto|test';
    mc_long_msg='eKB12345';
    mc_host='';
    mc_object_class='';
    mc_object='';
    mc_parameter='';
    msg='';
    groupe_affectation='EXPLOITATION_APPLICATIONS-TOTO';
    commentaire='DT123';
    END
  
    AUTOMATION;
    mc_long_msg='eKB007';
    ctm_application='test.';
    ctm_group='';
    ctm_jobname='';
    ctm_datacenter='';
    ctm_nodeid='';
    ctm_msg='';
    groupe_affectation='MCO_test';
    commentaire='DT01';
    END
  
    AUTOMATION;
    groupe_affectation='SUPPORT';
    msg_exception='APPLI 4';
    mc_long_msg='eKB007';
    commentaire='Automatic';
    END

Example of a complete playbook for testing

- hosts: localhost

  vars:

    test: "{{ out.stdout|
              split('END')|
              select|
              map('trim')|
              map('regex_replace', ';', '')|
              map('community.general.jc', 'ini') }}"

    blocks_del:
      - |
        AUTOMATION;
        groupe_affectation='Test'';
        msg_exception='APPLI 1';
        mc_long_msg='eKBX';
        commentaire='Automatic';
        END

    lines_del: "{{ blocks_del|map('split')|map('join', ' ') }}"

    lines: |
      {% filter from_yaml %}
      {% for i in test %}
      {% for k,v in i.items() %}
      {% if loop.index == 1 %}
      - {{ k }};
      {% else %}
        {{ k }}='{{ v }}';
      {% endif %}
      {% endfor %}
        END
      {% endfor %}
      {% endfilter %}

  tasks:

    - shell: cat PATH.baroc | egrep '.*;|END'
      register: out

    - debug:
        var: lines

    - debug:
        var: lines_del

    - debug:
        msg: |
          {% for i in lines|difference(lines_del) %}
          {% for j in i|split('; ') %}
          {{ j }}{% if not loop.last %};{% endif +%}
          {% endfor %}

          {% endfor %}

You can simplify the code by creating a list of dictionaries you want to delete. For example,

    blocks_del:
      - AUTOMATION: ''
        commentaire: Automatic
        groupe_affectation: Test'
        mc_long_msg: eKBX
        msg_exception: APPLI 1
      - PAPERBOY: ''
        commentaire: Automatic
        groupe_affectation: Test'
        mc_long_msg: eKB42
        msg_exception: APPLI 1

Then, you can directly iterate the difference

  test|difference(blocks_del):
  - AUTOMATION: ''
    application_infogerant: toto|test
    commentaire: DT123
    groupe_affectation: EXPLOITATION_APPLICATIONS-TOTO
    mc_host: ''
    mc_long_msg: eKB12345
    mc_object: ''
    mc_object_class: ''
    mc_parameter: ''
    mc_service: .\* - PRE-PRODUCTION
    msg: ''
  - AUTOMATION: ''
    commentaire: DT01
    ctm_application: test.
    ctm_datacenter: ''
    ctm_group: ''
    ctm_jobname: ''
    ctm_msg: ''
    ctm_nodeid: ''
    groupe_affectation: MCO_test
    mc_long_msg: eKB007
  - AUTOMATION: ''
    commentaire: Automatic
    groupe_affectation: SUPPORT
    mc_long_msg: eKB007
    msg_exception: APPLI 4

评论

0赞 Carvainth 10/12/2023
Hello, thanks for your answer. So there is two things to precise : - I have put the wrong entry to delete from the fil, PAPERBOY shouldn't be there, it should be as all the others Automation. I have replace the sentence but it should be always the same word in the begening and at the end of the file. - The user that want to delete a bloc doesn't know the content of the file, he only knows the eKB number. So he should only put as variable eKBXXX Moreover the file should be modified, the sections with " ####### XX " should be maintained