
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ía
split(/^(?=\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 awk
para 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