Tengo un archivo de registro similar a este formato.
test { seq-cont { 0, 67, 266 }, grp-id 505 } } test{ test1{ val } }Aquí está el comando echo para producir esa salida
$ echo -e "test {\nseq-cont {\n\t\t\t0,\n\t\t\t67,\n\t\t\t266\n\t\t\t},\n\t\tgrp-id 505\n\t}\n}\ntest{\n\ttest1{\n\t\tval\n\t}\n}\n"
La pregunta es cómo eliminar todos los espacios en blanco entre seq-cont { y el siguiente } que pueden ser múltiples en el archivo.
Quiero que la salida sea así. Preferiblemente use sed para producir la salida.
test{seq-cont{0,67,266}, grp-id 505 } } test{ test1{ val } }Esfuerzos de OP: aquí está el que funcionó un poco pero no exactamente lo que quería:
sed ':a;N;/{/s/[[:space:]]\+//;/}/s/}/}/;ta;P;D' logfileSe puede hacer usando gnu-awk con una expresión regular RS personalizada que coincida con { y cierre } :
awk -v RS='{[^}]+}' 'NR==1 {gsub(/[[:space:]]+/, "", RT)} {ORS=RT} 1' file test {seq-cont{0,67,266}, grp-id 505 } } test{ test1{ val } }Aquí:
NR==1 {gsub(/[[:space:]]+/, "", RT)} : para el primer registro, reemplace todos los espacios en blanco (incluidos los saltos de línea) con una cadena vacía.{ORS=RT} : establezca ORS en cualquier texto que hayamos capturado en RS PD: elimine NR==1 si desea hacer esto para todo el archivo.
Puedes hacerlo mucho más fácil con perl :
perl -0777 -i -pe 's/\s+(seq-cont\s*\{[^}]*\})/$1=~s|\s+||gr/ge' logfilepath La opción -0777 le dice a perl que absorba el archivo en una sola cadena, -i guarda los cambios en línea, \s+(seq-cont\s*\{[^}]*\}) regex coincide con uno o más espacios en blanco, luego captura en Grupo 1 ( $1 ) seq-cont , cero o más espacios en blanco, y luego una subcadena entre el carácter más a la izquierda { y el siguiente } ( [^}]* coincide con cero o más caracteres que no sean } ) y luego todos uno o más caracteres de espacio en blanco los fragmentos (emparejados con \s+ ) se eliminan de todo el valor del Grupo 1 ( $1 ) (este segundo reemplazo interno está habilitado con la bandera e ). Todas las ocurrencias se manejan debido a la bandera g (al lado de e ).
Vea la demostración en línea :
#!/bin/bash s=$(echo -e "test {\nseq-cont {\n\t\t\t0,\n\t\t\t67,\n\t\t\t266\n\t\t\t},\n\t\tgrp-id 505\n\t}\n}\ntest{\n\ttest1{\n\t\tval\n\t}\n}\n") perl -0777 -pe 's/\s+(seq-cont\s*\{[^}]*\})/$1=~s|\s+||gr/ge' <<< "$s"Producción:
test {seq-cont{0,67,266}, grp-id 505 } } test{ test1{ val } }Con sus muestras mostradas, intente seguir el programa awk . Probado y escrito en GNU awk .
awk -v RS= ' match($0,/{\nseq-cont {\n[^}]*/){ val=substr($0,RSTART,RLENGTH) gsub(/[[:space:]]+/,"",val) print substr($0,1,RSTART-1) val substr($0,RSTART+RLENGTH) } ' Input_file Explicación: la explicación simple sería usar la capacidad RS para establecerlo en nulo. Luego, use la función de match de awk para hacer coincidir todo entre seq-cont { hasta la próxima aparición de } . Eliminando todos los espacios, nuevas líneas en valor coincidente. Finalmente, imprima todos los valores, incluidos los valores recién editados, para obtener el resultado esperado mencionado por OP.