using your example file
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;}'
Convert every block of text to rows and using '*' to separate the fields
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
Sort fields within the lines and using '*' to separate the fields
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
rearrange the fieslds in the lines to 'print dn: x' in first place
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
Sorting the lines by the first column or field
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
Converting the rows to one column and inserting empty lines
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
I know I'm using too much steps.
dn
so simple as in the example? – andcoz Jan 21 at 16:18