如何从ansible中的文件中读取一段文本

How to read a block of text from a file in ansible

您好,我正在读取文件中的内容。

文件包含以下内容。

======

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

======

class BitWise extends And, Or, Xor, Not

// Implementation of the Interfaces goes here

======

我试图只读取接口

我经历了这个

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

我认为我在正则表达式部分做错了。但我不知道如何更正它以获得所需的 output.Could 任何人都可以帮助我解决问题。还有没有其他方法可以完成同样的任务。

在你的模式中 ^interface.+?=* 这部分 .+? 是非贪婪的,所以引擎会尽可能少地匹配 1+ 次。这部分 =* 匹配等号 0+ 次。

当界面中没有等号时,它只会匹配 interface 后跟一个 space 如果点不匹配换行符。

如果您想使用您的模式,您必须启用点匹配换行符(如果支持,请使用内联修饰符 (?s))。使用捕获组或正面前瞻来不匹配换行符和等号,但要确保它在那里。

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

Regex demo

另一个选项可能是匹配接口和线路的其余部分。然后重复匹配行,只要下一行不使用负先行 (?!=)

以等号开头
^interface\b.*(?:\r?\n(?!=).*)*

Regex demo

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

给予

"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 ...)

您可以组合 filters and tests 以获得您想要的结果:

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

这将 return:

[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);']