Я пытаюсь выполнить некоторую текстовую обработку файла с помощью скрипта 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:
найдено, то $0
d меняется на old, $0
за которым следует ORS
(новая строка), за которой следует variable a
.
решение4
Мы можем использовать конструкции POSIX sed, чтобы перевернуть указанные строки.
sed '/attr:/!x;$G' file