Пошаговая замена строк между двумя шаблонами регулярных выражений в файле

Пошаговая замена строк между двумя шаблонами регулярных выражений в файле

Я пытаюсь выполнить некоторую текстовую обработку файла с помощью скрипта bash. Цель состоит в том, чтобы взять все строки, начинающиеся с "field:" с отступом под меткой 'attribute:' и поменять их местами с соответствующей строкой, начинающейся с "- attr:", которая следует за ними.

На данный момент я думаю, что у меня есть шаблоны регулярных выражений, которые должны соответствовать меткам:

/ *field:(.*)/g

/ *- attr:(.*)/g

Но мне не удалось добиться успеха с логикой анализа нужных полей и правильной их замены.

Пример входного текста

- metric: 'example.metric.1'
  attributes:
      field: 'example 1'
    - attr: 'example1'
      field: 'example 2'
    - attr: 'example2'
      field: 'example 3'
    - attr: 'example3'
      field: 'example 4'
    - attr: 'example4'
- metric: 'example.metric.2'
  attributes:
      field: 'example 5'
    - attr: 'example5'
      field: 'example 6'
    - attr: 'example6'
      field: 'example 7'
    - attr: 'example7'
- metric: 'example.metric.3'
...

Желаемый результат

- metric: 'example.metric.1'
  attributes:
    - attr: 'example1'
      field: 'example 1'
    - attr: 'example2'
      field: 'example 2'
    - attr: 'example3'
      field: 'example 3'
    - attr: 'example4'
      field: 'example 4'
- metric: 'example.metric.2'
  attributes:
    - attr: 'example5'
      field: 'example 5'
    - attr: 'example6'
      field: 'example 6'
    - attr: 'example7'
      field: 'example 7'
- metric: 'example.metric.3'
... 

Как бы я этого добился?

решение1

Использование любого awk в любой оболочке на любой машине Unix:

$ awk '$1=="field:"{s=ORS $0; next} {print $0 s; s=""}' file
- metric: 'example.metric.1'
  attributes:
    - attr: 'example1'
      field: 'example 1'
    - attr: 'example2'
      field: 'example 2'
    - attr: 'example3'
      field: 'example 3'
    - attr: 'example4'
      field: 'example 4'
- metric: 'example.metric.2'
  attributes:
    - attr: 'example5'
      field: 'example 5'
    - attr: 'example6'
      field: 'example 6'
    - attr: 'example7'
      field: 'example 7'
- metric: 'example.metric.3'

если в некоторых строках у вас может отсутствовать пробел field:или по какой-то причине у вас есть жгучее желание использовать регулярное выражение, то измените $1=="field:"на $1~/^field:/или /^[[:space:]]*field:/, в зависимости от того, что вам больше нравится.

решение2

С sed:

sed -n '/^ *field: /{h;n;G};p' data

Если мы сопоставляем fieldключевое слово, то:

  • сохранить текущую строку в hold space( h)
  • получить следующую строку из файла в pattern space( n)
  • поменять местами pattern space( hold space) G(равнозначно замене строк)

выведите каждую встретившуюся вам строку:p

решение3

С использованием awk:

awk '{if ($1 == "field:") {a=$0;x=0} 
else if (/- attr:/) {$0 = $0 ORS a; x=1} else {x=1}}x' input

В этой команде, если field:найдено, то текущая входная запись( $0) сохраняется в переменную a, а x устанавливается в ноль. И если attr:найдено, то $0d меняется на old, $0за которым следует ORS(новая строка), за которой следует variable a.

решение4

Мы можем использовать конструкции POSIX sed, чтобы перевернуть указанные строки.

sed '/attr:/!x;$G' file

Связанный контент