
Ich muss eine LDIF-Datei sortieren, in der mehrere Zeilen zu einer übergeordneten Datei gehören.
Beispiel
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
zu diesem
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
Daher werden alle übergeordneten Zeilen, die mit dn beginnen, sortiert, darunter werden alle attrx sortiert und wenn attrx mehrere Werte hat, werden diese ebenfalls sortiert. Ich habe dies mit der Lesezeile gemacht, aber bei großen Dateien dauert das Stunden. Gibt es eine schnellere Möglichkeit, dasselbe mit Bash-Befehlen zu tun?
Ein Attributwert nimmt immer nur eine Zeile ein. Wenn mehrere Werte vorhanden sind, nimmt jeder eine Zeile ein. Keine Zeile ist base64-kodiert.
Antwort1
mithilfe Ihrer Beispieldatei
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;}'
Wandeln Sie jeden Textblock in Zeilen um und verwenden Sie '*', um die Felder zu trennen
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
Sortieren Sie die Felder innerhalb der Zeilen und verwenden Sie '*' um die Felder zu trennen
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
Ordnen Sie die Felder in den Zeilen so um, dass „print dn: x“ an erster Stelle steht.
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
Sortieren der Zeilen nach der ersten Spalte oder dem ersten Feld
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
Umwandlung der Zeilen in eine Spalte und Einfügen von Leerzeilen
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
Ich weiß, dass ich zu viele Schritte verwende.