Estoy intentando procesar un texto en un archivo usando un script bash. El objetivo es tomar todas las líneas que comienzan con "campo:" sangradas bajo una etiqueta 'atributo:' e intercambiarlas con la línea asociada que comienza con "- attr:" que sigue.
Hasta ahora creo que tengo patrones de expresiones regulares que deberían coincidir con las etiquetas:
/ *field:(.*)/g
/ *- attr:(.*)/g
Pero no he tenido éxito con la lógica para analizar los campos deseados y hacer que se intercambien correctamente.
Texto de entrada de ejemplo
- 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'
...
Salida deseada
- 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'
...
¿Cómo haría para lograr esto?
Respuesta1
Usando cualquier awk en cualquier shell en cada caja 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'
Si es posible que no tenga un espacio después field:
en algunas líneas o simplemente tenga un deseo ardiente de usar una expresión regular por algún motivo, cambie $1=="field:"
a $1~/^field:/
o /^[[:space:]]*field:/
, lo que prefiera.
Respuesta2
Con sed
:
sed -n '/^ *field: /{h;n;G};p' data
Si hacemos coincidir una field
palabra clave entonces:
- guardar la línea actual en
hold space
(h
) - obtener la siguiente línea del archivo en
pattern space
(n
) - intercambie el
pattern space
con elhold space
(G
) (Equivale al intercambio de línea)
Imprime cada línea que encuentres:p
Respuesta3
Usando awk
:
awk '{if ($1 == "field:") {a=$0;x=0}
else if (/- attr:/) {$0 = $0 ORS a; x=1} else {x=1}}x' input
En este comando, si field:
se encuentra, el registro de entrada actual ( $0
) se guarda en la variable a
y x se establece en cero. Y si attr:
se encuentra, $0
se cambia d a antiguo $0
seguido de ORS
(nueva línea) seguido de variable a
.
Respuesta4
Podemos usar construcciones sed POSIX para invertir dichas líneas.
sed '/attr:/!x;$G' file