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?
3 Réponses :
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(?!=).*)*
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=)
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 ...)
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 }}"
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