bash - 在 Yaml 中解析 Bash 数组

标签 bash ansible yaml

在 ansible 剧本中,我必须读取一个包含以下数据的 yaml 文件:

john: stu001
bob: stu002
william: stu003

这个数据是动态的,可以有学生的数量和他们的 id。我想在我的 ansible play 中阅读这个 yaml 并且需要像这样的输出:

---
- name: Students Data
  hosts: localhost
  tasks:
  - include_vars:
        file: tmp/stuData.yml
        name: stuName
  - name: "Students Details"
    uri:
      url: "{{ some_api_server }}"
      return_content: yes
      body_format: json
      method: POST
      body:
         matchers:
           - name: john
             id: stu001
             age: NA
           - name: bob
             id: stu002
             age: NA
           - name: william
             id: stu003
             age: NA
         startsAt: "{{ st_time }}"
         endsAt: "{{ en_time }}"
         createdBy: abc@example.com

我已经尝试了下面的代码:

---
- name: Students Data
  hosts: localhost
  tasks:
  - include_vars:
        file: tmp/stuData.yml
        stuName: stuName
  - name: "Students Details"
    uri:
      url: "{{ some_api_server }}"
      return_content: yes
      body_format: json
      method: POST
      body:
         matchers:
         {% for k,v in stuName.items() %}
           - name: {{ k }}
             id: {{ v }}
             age: "NA"   
         {% endfor %}
         startsAt: "{{ st_time }}"
         endsAt: "{{ en_time }}"
         createdBy: abc@example.com

这在匹配器之后的行中给我语法错误。谁能帮我写出正确的代码。

最佳答案

创建一个简单的脚本来写入哈希,例如

shell> cat /tmp/xyz.sh 
#!/bin/bash
declare -A animals=(["moo"]="cow" ["woof"]="dog")
for i in "${!animals[@]}"; do
    echo "$i: ${animals[$i]}"
done

给予

shell> /tmp/xyz.sh 
woof: dog
moo: cow

然后是任务

    - set_fact:
        xyz: "{{ lookup('pipe', '/tmp/xyz.sh')|from_yaml }}"

创建字典

  xyz:
    moo: cow
    woof: dog

现在您可以将数据格式化为任何结构,例如

    - set_fact:
        matchers: "{{ xyz|dict2items }}"

给出列表匹配器

  matchers:
  - key: woof
    value: dog
  - key: moo
    value: cow

<支持>

您可以更改属性的名称,例如

    - set_fact:
        matchers: "{{ xyz|dict2items(key_name='name', value_name='value') }}"

给予

  matchers:
  - name: woof
    value: dog
  - name: moo
    value: cow

然后,您可以添加属性 name 并将其放入列表中,例如

    - set_fact:
        _list: "{{ [{'name': 'xyz', 'matchers': matchers}] }}"

给出你正在寻找的结构

  _list:
  - matchers:
    - key: woof
      value: dog
    - key: moo
      value: cow
    name: xyz

问:将此动物变量传递给 yaml 文件

A:使用复制,例如

    - copy:
        dest: /tmp/xyz.yml
        content: |
          - name: xyz
            matchers:
          {% for k,v in xyz.items() %}
              - name: {{ k }}
                value: {{ v }}
          {% endfor %}

给予

shell> cat /tmp/xyz.yml 
- name: xyz
  matchers:
    - name: woof
      value: dog
    - name: moo
      value: cow

,或者您可以使用创建的列表,例如

    - copy:
        dest: /tmp/xyz.yml
        content: "{{ _list|to_yaml }}"

给予

shell> cat /tmp/xyz.yml 
- matchers:
  - {key: woof, value: dog}
  - {key: moo, value: cow}
  name: xyz

,或者您可以通过过滤器 to_nice_yaml 改进格式,例如

    - copy:
        dest: /tmp/xyz.yml
        content: "{{ _list|to_nice_yaml }}"

给予

shell> cat /tmp/xyz.yml 
-   matchers:
    -   key: woof
        value: dog
    -   key: moo
        value: cow
    name: xyz

问:代码的流程就像是首先执行 sh 文件,然后调用播放。

A:实际上没有区别。读取文件而不是在 pipe 查找中运行命令,例如

shell> /tmp/xyz.sh > /tmp/xyz.txt
shell> cat /tmp/xyz.txt
woof: dog
moo: cow

然后是任务

    - set_fact:
        xyz: "{{ lookup('file', '/tmp/xyz.txt')|from_yaml }}"

创建相同的字典

  xyz:
    moo: cow
    woof: dog

关于bash - 在 Yaml 中解析 Bash 数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67277142/

相关文章:

ruby - 防止在 Ruby 中将字符串转换为八进制数

bash - oarr=($output) 在 shell 中做什么?

linux - Bash 在 for 中跳过迭代

mysql - 每条街道的 LibreOffice Calc 电子表格 : Find highest house number, 并仅显示这些行

amazon-ec2 - 使用 ansible 通过标签启动之前停止的 EC2 实例

ruby-on-rails - ruby on rails 将两个 yaml 文件合并到一个唯一的 yml 文件中

bash - 如何将本地文件作为参数注入(inject)到在 docker 容器中运行的命令?

mysql - 使用 Ansible 任务运行 SELECT 查询

ansible - 如何使用ansible删除ecs服务

yaml - yq 将数据追加到 yaml 文件中