Ordenar archivos estructurados con comandos bash

Ordenar archivos estructurados con comandos bash

Necesito ordenar un archivo LDIF, donde varias líneas pertenecen a una principal.

Ejemplo

dn: 2

attr1: b

attr2: a

attr1: a

attr1: c



dn: 3

attr2: a

attr1: c

attr1: b

attr1: a



dn: 1

attr1: a

attr1: c

attr1: b

attr2: a

a este

dn: 1

attr1: a

attr1: b

attr1: c

attr2: a


dn: 2

attr1: a

attr1: b

attr1: c

attr2: a


dn: 3

attr1: a

attr1: b

attr1: c

attr2: a

Entonces, todas las líneas principales que comienzan con dn están ordenadas, debajo todos los attrx están ordenados y si attrx tiene múltiples valores, también están ordenados. He hecho esto con la línea de lectura, pero esto lleva horas en archivos grandes. ¿Existe una forma más rápida de hacer lo mismo con los comandos bash?

El valor de un atributo siempre ocupa solo una línea. Si hay varios valores, cada uno toma una línea. Ninguna línea está codificada en base64.

Respuesta1

usando su archivo de ejemplo

awk 'BEGIN {RS="\n\n\n";FS="\n\n";OFS="*";ORS=""} {print $1,$2,$3,$4,$5}' file |awk -F'*' '{for(i=1; i<=NF; i++) c[i]=$i; n=asort(c); for (i=1; i<=n; i++) printf "%s%s*", c[i], (i<n?OFS:RS); delete c}' |sed 's/^*//' |awk -F'*' '{print $5"*"$1"*"$2"*"$3"*"$4}' |sort |awk -F'*' 'BEGIN{OFS="\n\n";ORS="\n\n\n"} {print $1,$2,$3,$4,$5;}'

Convierta cada bloque de texto en filas y use '*' para separar los campos

awk 'BEGIN {RS="\n\n\n";FS="\n\n";OFS="*";ORS=""} {print $1,$2,$3,$4,$5}' file dn: 2*attr1: b*attr2: a*attr1: a*attr1: c dn: 3*attr2: a*attr1: c*attr1: b*attr1: a dn: 1*attr1: a*attr1: c*attr1: b*attr2: a

Ordene los campos dentro de las líneas y use '*' para separar los campos

awk 'BEGIN {RS="\n\n\n";FS="\n\n";OFS="*";ORS=""} {print $1,$2,$3,$4,$5}' file |awk -F'*' '{for(i=1; i<=NF; i++) c[i]=$i; n=asort(c); for (i=1; i<=n; i++) printf "%s%s*", c[i], (i<n?OFS:RS); delete c}' |sed 's/^*//'

attr1: a *attr1: b *attr1: c *attr2: a *dn: 2 attr1: a *attr1: b *attr1: c *attr2: a *dn: 3 attr1: a *attr1: b *attr1: c *attr2: a *dn: 1

reorganice los campos en las líneas para 'imprimir dn: x' en primer lugar

awk 'BEGIN {RS="\n\n\n";FS="\n\n";OFS="*";ORS=""} {print $1,$2,$3,$4,$5}' file |awk -F'*' '{for(i=1; i<=NF; i++) c[i]=$i; n=asort(c); for (i=1; i<=n; i++) printf "%s%s*", c[i], (i<n?OFS:RS); delete c}' |sed 's/^*//' |awk -F'*' '{print $5"*"$1"*"$2"*"$3"*"$4}'

dn: 2*attr1: a *attr1: b *attr1: c *attr2: a dn: 3*attr1: a *attr1: b *attr1: c *attr2: a dn: 1*attr1: a *attr1: b *attr1: c *attr2: a

Ordenar las líneas por la primera columna o campo

awk 'BEGIN {RS="\n\n\n";FS="\n\n";OFS="*";ORS=""} {print $1,$2,$3,$4,$5}' file |awk -F'*' '{for(i=1; i<=NF; i++) c[i]=$i; n=asort(c); for (i=1; i<=n; i++) printf "%s%s*", c[i], (i<n?OFS:RS); delete c}' |sed 's/^*//' |awk -F'*' '{print $5"*"$1"*"$2"*"$3"*"$4}' |sort

dn: 1*attr1: a *attr1: b *attr1: c *attr2: a dn: 2*attr1: a *attr1: b *attr1: c *attr2: a dn: 3*attr1: a *attr1: b *attr1: c *attr2: a

Convertir las filas a una columna e insertar líneas vacías

awk 'BEGIN {RS="\n\n\n";FS="\n\n";OFS="*";ORS=""} {print $1,$2,$3,$4,$5}' file |awk -F'*' '{for(i=1; i<=NF; i++) c[i]=$i; n=asort(c); for (i=1; i<=n; i++) printf "%s%s*", c[i], (i<n?OFS:RS); delete c}' |sed 's/^*//' |awk -F'*' '{print $5"*"$1"*"$2"*"$3"*"$4}' |sort |awk -F'*' 'BEGIN{OFS="\n\n";ORS="\n\n\n"} {print $1,$2,$3,$4,$5;}'

dn: 1

attr1: a

attr1: b

attr1: c

attr2: a


dn: 2

attr1: a

attr1: b

attr1: c

attr2: a


dn: 3

attr1: a

attr1: b

attr1: c

attr2: a

Sé que estoy usando demasiados pasos.

información relacionada