Estou tentando fazer algum processamento de texto em um arquivo usando um script bash. O objetivo é pegar todas as linhas que começam com "field:" recuadas sob um rótulo 'attribute:' e trocá-las pela linha associada que começa com "- attr:" a seguir.
Até agora acho que tenho padrões regex que devem corresponder aos rótulos:
/ *field:(.*)/g
/ *- attr:(.*)/g
Mas não tive sucesso com a lógica para analisar os campos desejados e fazer com que eles trocassem corretamente.
Exemplo de texto de entrada
- 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'
...
Saída Desejada
- 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'
...
Como eu faria para conseguir isso?
Responder1
Usando qualquer awk em qualquer shell em cada caixa 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'
se você não tiver um espaço depois field:
de algumas linhas ou apenas tiver um desejo ardente de usar um regexp por algum motivo, mude $1=="field:"
para $1~/^field:/
ou /^[[:space:]]*field:/
, o que preferir.
Responder2
Com sed
:
sed -n '/^ *field: /{h;n;G};p' data
Se correspondermos a uma field
palavra-chave, então:
- salve a linha atual no
hold space
(h
) - obtenha a próxima linha do arquivo no
pattern space
(n
) - troque o
pattern space
porhold space
(G
) (igual à troca de linha)
imprima cada linha que você encontrar:p
Responder3
Usando awk
:
awk '{if ($1 == "field:") {a=$0;x=0}
else if (/- attr:/) {$0 = $0 ORS a; x=1} else {x=1}}x' input
Neste comando, se field:
for encontrado, o registro de entrada atual ( $0
) será salvo na variável a
e x será definido como zero. E se attr:
for encontrado, $0
altere d para old $0
seguido de ORS
(nova linha) seguido de variável a
.
Responder4
Podemos usar construções POSIX sed para inverter as referidas linhas.
sed '/attr:/!x;$G' file