msort(1)
a été conçu pour être en mesure de trier les fichiers avec des enregistrements multi-lignes. Il a une interface graphique facultative, ainsi qu'une version de ligne de commande normale et utilisable pour les humains. (Du moins, les humains qui aiment lire attentivement les manuels et chercher des exemples...)
AFAICT, vous ne pouvez pas utiliser un modèle arbitraire pour les enregistrements, donc à moins que vos enregistrements ne soient de taille fixe (en octets, pas en caractères ou en lignes). msort
a un -b
option pour les enregistrements qui sont des blocs de lignes séparés par des lignes vides.
Vous pouvez transformer votre entrée dans un format qui fonctionnera avec -b
assez facilement, en mettant une ligne vide avant chaque ###...
(sauf le premier).
Par défaut, il imprime des statistiques sur stderr, donc au moins il est facile de dire quand il n'a pas trié parce qu'il pensait que toute l'entrée était un seul enregistrement.
msort
fonctionne sur vos données. Le sed
la commande ajoute une nouvelle ligne à chaque #+
ligne sauf la ligne 1. -w
trie l'intégralité de l'enregistrement (lexicographiquement). Il existe des options pour choisir quelle partie d'un enregistrement utiliser comme clé, mais je n'en ai pas eu besoin.
J'ai également laissé de côté la suppression des retours à la ligne supplémentaires.
$ 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
Je n'ai pas eu de chance avec -r '#'
pour l'utiliser comme séparateur d'enregistrements. Il pensait que le fichier entier était un seul enregistrement.
Une solution consiste à remplacer d'abord les sauts de ligne à l'intérieur d'un bloc par un caractère inutilisé de votre choix ('|' dans l'exemple ci-dessous), à trier le résultat et à remplacer le séparateur choisi par le saut de ligne d'origine :
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
avale tout le fichier/(....)/g
faire correspondre et extraire les enregistrementsprint sort ...
triez-les et imprimez-les