web-dev-qa-db-fra.com

GNU tri tri stable lorsque tri ne connaît pas l'ordre de tri

J'ai un fichier à deux colonnes; le fichier est déjà trié comme je le souhaite dans la colonne 1. Je voudrais trier sur la colonne 2, dans chaque catégorie de la colonne 1. Cependant, sort ne comprend pas l'ordre de tri de la colonne 1.

La manière normale (à partir de questions similaires ici sur la pile) serait la suivante:

sort --stable -k1,1 -k2,2n

Mais je ne peux pas spécifier le tri sur k1, car il est arbitraire.

Exemple d'entrée:

C 2
C 1
A 2
A 1
B 2 
B 1

et sortie:

C 1
C 2
A 1
A 2
B 1 
B 2
18
Evan Benn

Vous pouvez utiliser awk pour démarrer un nouveau tri pour chaque bloc:

% awk -v cmd="sort -k2,2" '$1 != prev {close(cmd); prev=$1} {print | cmd}' foo
C 1
C 2
A 1
A 2
B 1
B 2
  • $1 != prev {close(cmd); prev=$1} - lorsque la valeur enregistrée est différente, nous avons un nouveau bloc, donc nous fermons tout précédemment commencé sort
  • {print | "sort -k2,2"}' Dirige la sortie vers sort, en la démarrant si elle n'est pas déjà en cours d'exécution (awk peut garder une trace des commandes qu'elle démarre)
20
muru

Vous pouvez utiliser une transformation de Schwartzian (c'est essentiellement l'approche décorer-trier-décorer que vous avez mentionnée dans un commentaire, mais probablement plus performante que celle de murbonne réponse en raison de l'utilisation d'une seule invocation sort par opposition à plusieurs) - en utilisant awk ajoutez une colonne de préfixe qui s'incrémente avec un changement de valeur dans la première colonne, triez par la colonne de préfixe suivi de la "deuxième" colonne (dont la position ordinale est temporairement passée à 3 en raison de la présence de la colonne préfixe), et enfin se débarrasser de la colonne préfixe

awk '{print ($1 in a? c+0: ++c)"\t" $0; a[$1]}' file | sort -k1,1n  -k3,3 | cut -f 2-
12
iruvar