Ordenar archivo por grupo de líneas

Ordenar archivo por grupo de líneas

Si tengo un archivo con contenidos similares a:

FirstSection
    Unique first line in first section
    Unique second line in first section

SecondSection
    Unique first line in second section
    Unique second line in second section

...

NthSection
    Unique first line in Nth section
    Unique second line in Nth section

¿Es posible utilizar comandos Unix (por ejemplo, sort, awk) para ordenar el archivo alfabéticamente por la primera línea sin sangría en cada grupo de tres líneas, manteniendo las líneas sangradas en su grupo existente?

Respuesta1

Usando Perl puedes ejecutar algo como:

  • sorber el archivo ( perl -0n)
  • dividir la entrada por líneas sin sangríasplit(/^(?=\S)/m)
  • ordenar e imprimir

perl -0ne 'print sort split(/^(?=\S)/m) ' ex 

Respuesta2

El primer sed coloca cada sección en una sola línea, usando el texto <EOL>como delimitador entre las líneas de la sección. Luego ordeno las secciones y uso el segundo sed para revertir cada una <EOL>a una nueva línea.

sed -r ':r;$!{N;br};s:\n([[:blank:]])(\1*):<EOL>\1\2:g' file|sort|sed -r '/^$/d;:l;G;s:(.*)<EOL>(.*)(\n):\1\3\2:;tl;$s:\n$::'

No elegí un carácter como delimitador, ya que el archivo de entrada podría tenerlo, así que lo usé <EOL>en su lugar.

Producción:Agregué una nueva línea después de cada sección, excepto la última, para recrear el estilo del archivo de entrada.

FirstSection
    Unique first line in first section
    Unique second line in first section

NthSection
    Unique first line in Nth section
    Unique second line in Nth section

SecondSection
    Unique first line in second section
    Unique second line in second section

Respuesta3

con GNU awkpara asort()y PROCINFO["sorted_in"]podríamos mantener cada grupo de registros en una matriz asociada a awk basada en saltos de línea entre cada grupo; luego ordene la matriz asort()e imprima todos los grupos dentro de un bucle for.

awk '/^$/{ ++grpNr; next }
{ groups[grpNr]=(groups[grpNr]==""? "" : groups[grpNr] RS) $0 }
END{ asort(groups); 
     for(grp in groups) print groups[grp]
}'  infile

nota: puedes usar PROCINFO["sorted_in"]el elemento para establecer qué tipo de clasificación necesitas; por ejemplo PROCINFO["sorted_in"]="@val_str_desc"ordenará elvaleue de nuestra matriz comocadenaing y endescorden.


O con cualquiera awk(para producir bloques de registros delimitados por Nul) + sort -z(para ordenar según el carácter Nul, no por Nueva línea) + tr(para eliminar el carácter Nul agregado previamente awk):

<infile awk '/^$/{ ++grpNr; next }
{ groups[grpNr]=(groups[grpNr]==""? "\0" : groups[grpNr] RS) $0 }
END{ for(grp in groups) print groups[grp] }' |sort -z |tr -d '\0'

probando en un archivo de entrada como:

BFirstSection
    Unique first line in first section
    Unique second line in first section

DSecondSection
    Unique first line in second section
    Unique second line in second section

Aanothersection...
    ...
    ...

CfourthSection
    Unique first line in Nth section
    Unique second line in Nth section

obtendrás un resultado como:

Aanothersection...
    ...
    ...
BFirstSection
    Unique first line in first section
    Unique second line in first section
CfourthSection
    Unique first line in Nth section
    Unique second line in Nth section
DSecondSection
    Unique first line in second section
    Unique second line in second section

información relacionada