Как прочитать блок текста из файла в ansible - PullRequest
1 голос
/ 13 июня 2019

Привет, я читаю содержимое из файла.

Файл содержит следующее содержимое.

======

интерфейс А

public void и (int, int);

public void nand (int, int);

======

интерфейс или

 public void or(int, int);

 public void nor(int, int);

======

интерфейс Xor

 public void xor(int, int);

 public void xnor(int, int);

======

интерфейс Не

 public void not(int);

======

класс BitWise расширяет А, Или, Xor, Не

// Здесь идет реализация интерфейсов

======

Я пытаюсь читать только интерфейсы

Я прошел через это Как прочитать определенную часть файла в ansible

---
 - 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

Вывод программ:

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

Но желаемый вывод

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)",
    ]
}

Я думаю, что я делаю что-то не так в части регулярных выражений. Но я не знаю, как это исправить, чтобы получить желаемый результат. Может ли кто-нибудь помочь мне решить проблему. И есть ли другой способ сделать то же самое?

Ответы [ 3 ]

1 голос
/ 13 июня 2019

Если у вас есть список заголовков в my_interfaces , можно будет использовать sed и вывести диапазон строк.

Задачи ниже

- 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

1010 * дают *

"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);", 
        "======"
    ]
]

(форматирование wip ...)

1 голос
/ 13 июня 2019

Вы можете комбинировать фильтры и тесты , чтобы получить желаемый результат:

---
- 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 }}"

Вы также можете объединить все шаги в одну команду:

---
- 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 }}"

Это вернет:

[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);']
1 голос
/ 13 июня 2019

В вашем шаблоне ^interface.+?=* эта часть .+? не является жадной, поэтому двигатель будет соответствовать 1+ раз как можно меньше.Эта часть =* соответствует знаку равенства 0+ раз.

Если в интерфейсе нет знака равенства, она будет совпадать только с interface, за которым следует пробел, если точка не соответствует символу новой строки.

Вы должны разрешить, чтобы точка совпадала с новой строкой (используйте встроенный модификатор (?s), если поддерживается), если вы хотите использовать свой шаблон.Используйте группу захвата или положительный прогноз, чтобы не совпадать с новой строкой и знаками равенства, но убедитесь, что она есть.

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

Regex demo

Другой вариантможет соответствовать интерфейсу и остальной части линии.Затем повторяйте совпадающие строки до тех пор, пока следующая строка не начинается со знака равенства, используя отрицательный прогноз (?!=)

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

Regex demo

...