msort(1)
è stato progettato per poter ordinare file con record multilinea. Ha un'interfaccia grafica opzionale, oltre a una versione a riga di comando normale e utilizzabile per gli umani. (Almeno, umani a cui piace leggere attentamente i manuali e cercare esempi...)
AFAICT, non puoi utilizzare uno schema arbitrario per i record, quindi a meno che i tuoi record non siano di dimensioni fisse (in byte, non caratteri o righe). msort
ha un -b
opzione per i record che sono blocchi di righe separate da righe vuote.
Puoi trasformare il tuo input in un formato che funzioni con -b
abbastanza facilmente, inserendo una riga vuota prima di ogni ###...
(tranne il primo).
Per impostazione predefinita, stampa le statistiche su stderr, quindi almeno è facile capire quando non ha eseguito l'ordinamento perché pensava che l'intero input fosse un singolo record.
msort
funziona sui tuoi dati. Il sed
comando antepone una nuova riga a ogni #+
riga tranne la riga 1. -w
ordina l'intero record (lessicograficamente). Ci sono opzioni per scegliere quale parte di un record utilizzare come chiave, ma non ne avevo bisogno.
Ho anche tralasciato di rimuovere le nuove righe extra.
$ sed '2,$ s/^#\+/\n&/' unsorted.records | msort -b -w 2>/dev/null
####################################
KEY1
VAL11
VAL12
VAL13
VAL14
####################################
KEY2
VAL21
VAL22
VAL23
VAL24
####################################
KEY3
VAL31
VAL32
VAL33
VAL34
Non ho avuto fortuna con -r '#'
per usarlo come separatore di record. Pensava che l'intero file fosse un record.
Una soluzione è cambiare prima i feed di riga all'interno di un blocco con un carattere inutilizzato di tua scelta ('|' nell'esempio seguente), per ordinare il risultato e riportare il separatore scelto al feed di riga originale:
sed -e 'N; N; N; N; N; s/\n/|/g' file.txt \
| sort -k2,2 -t\| \
| sed 's/|/\n/g'
perl -0ne 'print sort /(#+[^#]*)/g' file.txt
perl -0
recupera l'intero file/(....)/g
confronta ed estrai i recordprint sort ...
ordinali e stampali