Нужна помощь в bask awk, чтобы обновить файл Yaml, найдя шаблон в файле

#awk #yaml #line

Вопрос:

КОНТЕКСТ: Я очень новичок в написании сценариев UNIX и bash .

У меня есть .bash сценарий, который принимает .yaml и массив виртуальных машин, переданных в качестве аргументов.

(например)

 myscript.sh my.yaml neo1 neo2 neo3 alice1 alice2 alice3
 

Как найти шаблон ключа monitor_vm и записать последнюю строку раздела этого монитора и добавить в последние строки этого раздела?

У меня есть один пример функции, которая идентифицирует некоторый шаблон, чтобы указать номер строки этой вставляемой строки ….но это требует некоторых изменений. Пожалуйста, посоветуйте пример

 getline() {
  awk '
    BEGIN { monitor_vms="'${}'"; ln=1; fnd=0; }
      (fnd==1 amp;amp; $0 ~ /^  [a-z]/) { exit }
      ($0~/^monitor_vms:/) { fnd = 1 }
      ($0 ~ /./ amp;amp; $0 !~ /^#/) { ln = NR }
    END { print ln }' ${1}
}


for name in $VM_LIST; do
  line=`getline my.yaml monitor_vms`
  sed -i -e ${line}"a- name: "${vmname}"n my.yaml
done
 

Файл my.yaml выглядит следующим образом:

 ---
- someotherkey: hello
  value: some_value
- someotherkey1: hello1
  value1: some_value1
- monitor_vms:
  - name:  sujana
    cnt: 5
  - name: vijaya
    cnt: 5
- static_configs:
  - location:
    datacenter: 
 

Я ожидал бы получить требуемое my.yaml , после обновления:

 ---
- someotherkey: hello
  value: some_value
- someotherkey1: hello1
  value1: some_value1
- monitor_vms:
  - name:  sujana
    cnt: 5
  - name: vijaya
    cnt: 5
  - name: neo1
  - name: neo2
  - name: neo3
  - name: alice1
  - name: alice2
  - name: alice3
- static_configs:
  - location:
    datacenter: 
 

Комментарии:

1. 🙂 по ошибке. По стандарту это 3 тире . Хороший улов @EdMorton

Ответ №1:

Вам никогда не нужен sed, когда вы используете awk, вы позволяете переменным оболочки расширяться, чтобы стать частью сценариев, и в вашем коде есть другие ошибки оболочки. В качестве отправной точки вам следует скопировать/вставить все ваши сценарии в http://shellcheck.net и исправьте ошибки, о которых он вам рассказывает.

Это использует GNU awk для редактирования «на месте», так как вы использовали GNU sed для того же:

 $ cat myscript.sh
#!/usr/bin/env bash

file="$1"
shift
awk -i inplace -v vms="$*" '
/^-/ {
    if ( $2 == "monitor_vms:" ) {
        inBlock = 1
    }
    else {
        prtVms()
    }
}
$1 == "-" {
    prev = $0
}
{ print }
END { prtVms() }

function prtVms(    vmsArr, i, n) {
    if ( inBlock ) {
        sub(/:.*/,":",prev)
        n = split(vms,vmsArr)
        for (i=1; i<=n; i  ) {
            print prev, vmsArr[i]
        }
    }
    inBlock = 0
}
' "$file"
 
 $ cat my.yaml
---
- someotherkey: hello
  value: some_value
- someotherkey1: hello1
  value1: some_value1
- monitor_vms:
    - name:  sujana
      cnt: 5
    - name: vijaya
      cnt: 5
- static_configs:
   -  location:
      datacenter:
 
 $ ./myscript.sh my.yaml neo1 neo2 neo3 alice1 alice2 alice3
 
 $ cat my.yaml
---
- someotherkey: hello
  value: some_value
- someotherkey1: hello1
  value1: some_value1
- monitor_vms:
    - name:  sujana
      cnt: 5
    - name: vijaya
      cnt: 5
    - name: neo1
    - name: neo2
    - name: neo3
    - name: alice1
    - name: alice2
    - name: alice3
- static_configs:
   -  location:
      datacenter:
 

Комментарии:

1. Спасибо тебе, Эд Мортон. Когда я пытался запустить, я получал такую ошибку. Не уверен, что я делаю не так………?? Использование: awk [параметры стиля POSIX или GNU] -файл прогфайла f [ — ]… Использование: awk [параметры стиля POSIX или GNU] [ — ] файл «программа»… Параметры POSIX: длинные параметры GNU: (стандартные) -f файл программы —файл=файл программы-F fs —разделитель полей=fs -v var=val —назначить=var=val Короткие параметры: длинные параметры GNU: ………..

2. Я предполагаю, что вы используете очень старую версию gawk. Что awk --version выводит? Если это не GNU Awk 5.1.0 так или новее, установите новую версию gawk, так как ваша устарела. Если вы по какой-то причине не можете этого сделать, просто избавьтесь от этой -i inplace опции и сделайте tmp=$(mktemp) amp;amp; awk 'script' file > "$tmp" amp;amp; mv -- "$tmp" file так, как вы сделали бы с любым инструментом, чтобы перезаписать исходный входной файл выводом инструмента. Это будет работать с любым awk, и это то, что sed, awk, perl, ruby, python и т. Д. Делают в фоновом режиме при вызове с возможностью так называемого редактирования «на месте» в любом случае.