同时递归搜索和替换值

Searching and replacing values recursively in the same time

我有一个 Ansible playbook 文件夹,我想在其中 grep 特定的 YAML 块并用 playbook 文件夹中的值替换其中一个 Jinja2 变量。

例如:

grep -R -A 35 -w -h 'test_profiles:' .

test_profiles:
  - name: test_1
  source: '{{ service_name }}'
  

所以我想用它的值

插入 service_name 变量

我尝试的是对 service_name 进行 grep,但无法找到一种方法将变量递归替换为每个剧本文件夹的各自搜索结果

文件夹结构:

main.yml 来自剧本 1 示例:

---
service_name: 'service 1'

main.yml 来自剧本 2 示例:

---
service_name: 'service 2'

file.yml 来自剧本 1 示例:

---
test_profiles:
  - name: test_1
  source: '{{ service_name }}'

other_header:
   key: value

file.yml 来自剧本 2 示例:

---
test_profiles:
  - name: test_2
  source: '{{ service_name }}'

another_header:
   another_key: value

预期结果:

test_profiles:
  - name: test_1
  source: 'service 1'
test_profiles:
  - name: test_2
  source: 'service 2'
test_profiles:
  - name: test_3
  source: 'service 3'

grep 命令我试图获取 service_name 变量:

grep -R -oE 'service_name=([a-zA-Z]*-*[a-zA-Z]*)*|service_name:(\s*[a-zA-Z]*-*[a-zA-Z]*)*' .

但我找不到一种方法来组合这两个命令,以产生上述预期结果。

此解决方案每个剧本运行一个 awk。解析 main.yml 并存储 service_name 的值。解析第二个文件并仅打印替换了变量的行块(以 test_profiles: 开始并以空行或仅以 white-space 字符结束)。您从目录结构的根目录执行以下脚本。

#!/bin/bash

for d in playbook*; do
    [[ -f "$d"/main.yml ]] && [[ -f "$d"/tasks/file.yml ]] || continue
    awk -F"'" 'FNR==NR && /^service_name:/{s=;next} {FS=OFS}
           /test_profiles:/ {f=1}
           f {gsub("{{ service_name }}",s)}
           f && (NF==0) {f=0}
           f' "$d"/main.yml "$d"/tasks/file.yml
done

此外,如果 main.yml 中没有值,则会为 {{ service_name }} 打印空字符串,如果这不是功能而是错误,我们可以更改它。任何没有两个文件的剧本都会被忽略。


参考:

How to read two files with awk (NR==FNR)

gsub and the other GNU awk string functions

How to print using a flag a block between start and end pattern