Classificando arquivo estruturado com comandos bash

Classificando arquivo estruturado com comandos bash

Preciso classificar um arquivo LDIF, onde há várias linhas pertencentes a um arquivo pai.

Exemplo

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

para 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

Portanto, todas as linhas pai começando com dn são classificadas, abaixo de todos os attrx são classificados e se attrx tiver vários valores, eles também serão classificados. Eu fiz isso com a linha de leitura, mas isso leva horas em arquivos enormes. Existe uma maneira mais rápida de fazer o mesmo com comandos bash?

Um valor de atributo sempre ocupa apenas uma linha. Se houver vários valores, cada um usa uma linha. Nenhuma linha é codificada em base64.

Responder1

usando seu arquivo de exemplo

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;}'

Converta cada bloco de texto em linhas e use '*' para separar os 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

Classifique os campos dentro das linhas e use '*' para separar os 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

reorganize os campos nas linhas para 'print dn: x' em primeiro 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

Classificando as linhas pela primeira coluna ou 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

Convertendo as linhas em uma coluna e inserindo linhas vazias

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

Eu sei que estou usando muitos passos.

informação relacionada