2
votes

Comment lire un bloc de texte à partir d'un fichier dans ansible

Bonjour, je lis le contenu d'un fichier.

Le fichier contient le contenu suivant.

======

interface Et

public void et (int, int);

public void nand (int, int);

======

interface Ou

ok: [127.0.0.1] => {
    "my_interfaces": [
        "interface And \n public void and(int, int) \n public void nand(int, int)",
        "interface Or \n public void or(int, int) \n public void nor(int, int)",
        "interface Xor \n public void xor(int, int) \n public void xnor(int, int)",
        "interface Not \n public void not(int)",
    ]
}

======

interface Xor

ok: [127.0.0.1] => {
    "my_interfaces": [
        "interface And",
        "interface Or",
        "interface Xor",
        "interface Not"
    ]
}

======

interface non

---
 - name: Read the Interfaces
   hosts: 127.0.0.1
   connection: local
   vars:
      - file_path: " {{ playbook_dir }}/input_file.txt"
      - my_interfaces: []
   tasks:
         - name: Reading the interfaces
           set_fact:
                   my_interfaces: "{{ my_interfaces + [ item ] }}"
           with_lines: "cat {{file_path}}"
           when: item is search('^interface.+?=*')
         - name: Printing all the interfaces
           debug:
                  var: my_interfaces

======

la classe BitWise étend And, Or, Xor, Not

// La mise en œuvre des interfaces se fait ici

======

J'essaie de lire uniquement les interfaces

J'ai parcouru ceci Comment lire une partie particulière du fichier dans ansible

 public void not(int);

La sortie des programmes est p >

 public void xor(int, int);

 public void xnor(int, int);

Mais la sortie souhaitée est

 public void or(int, int);

 public void nor(int, int);

Je pense que je fais quelque chose de mal dans la partie expression régulière. Mais je ne sais pas comment le corriger pour obtenir le résultat souhaité. Quelqu'un pourrait-il m'aider à résoudre le problème. Et y a-t-il un autre moyen que celui-ci de faire la même tâche?


1 commentaires

Vous devez avoir le point macht une nouvelle ligne et utiliser 1+ fois un signe égal, sinon tout ce qui suit interface sera optionnel (? S) ^ interface \ b. +? \ R? \ n = + . Utilisez (? S) si pris en charge. Voir regex101.com/r/gTV7tJ/1


3 Réponses :


1
votes

Dans votre modèle ^ interface. +? = * cette partie . +? n'est pas gourmande, donc le moteur correspondrait 1+ fois le moins possible. Cette partie = * correspond à un signe égal plus de 0 fois.

Lorsqu'il n'y a pas de signe égal dans l'interface, elle ne correspondra qu'à interface suivie d'un espace si le le point ne correspond pas à une nouvelle ligne.

Vous devez activer que le point corresponde à une nouvelle ligne (utilisez un modificateur en ligne (? s) si pris en charge) si vous souhaitez utiliser votre modèle . Utilisez un groupe de capture ou une anticipation positive pour ne pas correspondre à la nouvelle ligne et aux signes égal, mais assurez-vous qu'il est là.

^interface\b.*(?:\r?\n(?!=).*)*

Démo Regex

Une autre option pourrait être de faire correspondre l'interface et le reste de la ligne. Ensuite, répétez les lignes correspondantes tant que la ligne suivante ne commence pas par un signe égal en utilisant une anticipation négative (?!=)

(?s)^interface\b.+?(?=\r?\n=)

Démo Regex


0 commentaires

1
votes

Une fois que vous avez la liste des titres dans mes_interfaces , il serait possible d'utiliser sed et d'imprimer la plage des lignes.

Les tâches ci-dessous p>

"my_ifc": [
    [
        "interface And", 
        "", 
        "public void and(int, int);", 
        "", 
        "public void nand(int, int);", 
        "", 
        "======"
    ], 
    [
        "interface Or", 
        "", 
        " public void or(int, int);", 
        "", 
        " public void nor(int, int);", 
        "======"
    ], 
    [
        "interface Xor", 
        "", 
        " public void xor(int, int);", 
        "", 
        " public void xnor(int, int);", 
        "======"
    ], 
    [
        "interface Not", 
        "", 
        " public void not(int);", 
        "======"
    ]
]

donne

- command: "sed -n '/{{ item }}/,/======/p' {{ file_path }}"
  register: result
  loop: "{{ my_interfaces }}"
- set_fact:
    my_ifc: "{{ my_ifc|default([]) + [ item.stdout_lines ] }}"
  loop: "{{ result.results }}"
- debug:
    var: my_ifc

(formatage wip ...)


0 commentaires

2
votes

Vous pouvez combiner des filtres et tests pour obtenir le résultat souhaité:

[u'interface And\n\npublic void and(int, int);\n\npublic void nand(int, int);',
 u'interface Or\n\n public void or(int, int);\n\n public void nor(int, int);',
 u'interface Xor\n\n public void xor(int, int);\n\n public void xnor(int, int);',
 u'interface Not\n\n public void not(int);']

Vous pouvez combinez également toutes les étapes dans une seule commande:

---
- hosts: localhost
  gather_facts: false
  vars:
      content: "{{ lookup('file', 'filename') }}"
  tasks:
    - name: "fetch interfaces"
      set_fact:
          content: "{{ content.split('======') | map('trim') | select('search', '^interface') | list }}"
    - debug:
          msg: "{{ content }}"

Cela renverra:

---
- hosts: localhost
  gather_facts: false
  vars:
      content: "{{ lookup('file', 'filename') }}"
  tasks:
    - name: "split file into blocks"
      set_fact:
          content: "{{ content.split('======') }}"
    - debug:
          msg: "{{ content }}"
    - name: "remove white space from start and end of blocks"
      set_fact:
          content: "{{ content | map('trim') | list}}"
    - debug:
          msg: "{{ content }}"
    - name: "select blocks that start with interface"
      set_fact:
          content: "{{ content | select('search', '^interface') | list}}"
    - debug:
          msg: "{{ content }}"


0 commentaires