Bash : erreurs en triant un fichier simple avec sort

Bonjour à tous,
je veux trier en bash un fichier lili.txt du type :

69 97 91 23 f
54 31 87 14 p
98 23 58 0 k
31 71 53 79 e
56 31 23 75 z
54 31 87 8 x
9 97 38 45 r
53 97 55 49 p
94 31 23 18 h
76 31 23 75 u

selon le champ n seul (ici les champs sont séparés par un blanc) ou du champ n1 au champ n2 et pas au-delà.
Dès le départ il y a une anomalie puisque :
sort -n lili.txt
donne :

54 31 87 8 x
98 23 58 0 k
9 97 38 45 r
31 71 53 79 e
53 97 55 49 p
54 31 87 14 p
56 31 23 75 z
69 97 91 23 f
76 31 23 75 u
94 31 23 18 h

Pourquoi le 9 de la première colonne est-il après le 54 et le 98 ?

sort -k2n, sort -k4n, sort -k5d donnent le résultat attendu mais
sort -k1n donne le même résultat faux que sort -n et sort -k2n,4n donne :

98 23 58 0 k
54 31 87 8 x
94 31 23 18 h
56 31 23 75 z
76 31 23 75 u
54 31 87 14 p
31 71 53 79 e
9 97 38 45 r
53 97 55 49 p
69 97 91 23 f

ce qui ne va pas non plus puisque la 2ème colonne est bien classée mais pas la troisième.
Il semble qu’il y ait un problème avec les nombres à un seul chiffre.

Pas de pb chez moi

cat lili.txt ; echo "########"; sort -n lili.txt
69 97 91 23 f
54 31 87 14 p
98 23 58 0 k
31 71 53 79 e
56 31 23 75 z
54 31 87 8 x
9 97 38 45 r
53 97 55 49 p
94 31 23 18 h
76 31 23 75 u
########
9 97 38 45 r
31 71 53 79 e
53 97 55 49 p
54 31 87 14 p
54 31 87 8 x
56 31 23 75 z
69 97 91 23 f
76 31 23 75 u
94 31 23 18 h
98 23 58 0 k

De mon côté, ça donne ça :

cat lili.txt ; echo '########' ; sort -n lili.txt ; echo '########' ; sort -k2n,4n lili.txt
69 97 91 23 f
54 31 87 14 p
98 23 58 0 k
31 71 53 79 e
56 31 23 75 z
54 31 87 8 x
9 97 38 45 r
53 97 55 49 p
94 31 23 18 h
76 31 23 75 u
########
9 97 38 45 r
31 71 53 79 e
53 97 55 49 p
54 31 87 14 p
54 31 87 8 x
56 31 23 75 z
69 97 91 23 f
76 31 23 75 u
94 31 23 18 h
98 23 58 0 k
########
98 23 58 0 k
54 31 87 14 p
54 31 87 8 x
56 31 23 75 z
76 31 23 75 u
94 31 23 18 h
31 71 53 79 e
53 97 55 49 p
69 97 91 23 f
9 97 38 45 r

Peux-tu donner les retours des commandes :

  • cat /etc/debian_version
  • which sort

Almtesh : merci pour ta réponse.
cat /etc/debian_version
9.6
which sort
/usr/bin/sort
J’ai vérifié que le fichier ne contenait pas de vice caché par un :
cat -etv lili.txt

PmGs : merci.
Et que te dit, s’il te plaît :
sort -k2n,4n lili.txt
?

sort -n : comparer selon la valeur numérique de la chaîne
de la chaîne pas du premier caractère
ainsi, chezmoi le sort de lili donne
54…
98…
9…
mais si je fais un fichier avec seulement les premeirs nombres
j’obtiens
9
31
53
54

-g serait-il plus adapté ?
-g, --general-numeric-sort
comparer selon la valeur numérique des caractères

que donne echo $BASH ? Pour toi almtesh aussi ça m’intrigue tes résultats. moi ça donne /bin/bash

cat /etc/debian_version
9.13
which sort
/usr/bin/sort
dpkg -S /usr/bin/sort
coreutils: /usr/bin/sort
sort --version
sort (GNU coreutils) 8.26

mais sur ma 10.5 j’ai comme almtesh
sort --version
sort (GNU coreutils) 8.30

d’après cette page
https://www.gnu.org/software/coreutils/manual/html_node/sort-invocation.html#DOCF2
ça dépend largement des LC_ ( des variables de langue )

conclusion rajouter
LC_ALL=C devant :
LC_ALL=C sort -n lili.txt

--debug aide bbien par exemple
sort -n lili.txt --debug

et en deb9 et deb10 on a le bon résultat

Ta référence :
https://www.gnu.org/software/coreutils/manual/html_node/sort-invocation.html#DOCF2
est assez éclairante.
Par exemple :
sort -k1,1n lili.txt
ne donne pas le même résultat que :
sort -k1n lili.txt
et :
sort -k2,2n -k3,3n -k4,4n -k5,5d lili.txt
classe tout bien comme il faut à partir du deuxième champ.
Avec ça et ton LC_ALL=C je suis loin de tout comprendre mais j’ai du grain à moudre. Merci !

Sinon je suis étonné que ça puisse avoir un rapport avec la version de Debian, le résultat du which sort ou de la valeur de $BASH ?

désolé j’ai écrit en suivant mes pensées
oublie le bash et le which sort ou la version de sort

imagine que tu veuilles trier alphabétiquement
éaàe
en français ça donne aàeé
en php ça donne aeàé ( avec ord() )
il faut lui dire comment choisir , d’où le LC_ALL, sinon il fait un truc que personne ne connaît vraiment

( tapes env |grep LC chez toi)

PS
j’ai trouvé le lien grace à man sort

En effet :

$ man sort | grep WARN
       *** WARNING *** The locale specified by the environment affects sort order.  Set LC_ALL=C to get the traditional sort order that uses native byte values.

Ainsi que

$ env | grep LANG

Ou sinon

$ locale

1 J'aime

version de Debian : NON
which sort : peu probable mais on peut tout imaginer

Par contre comme le précise ‹ dindoun › cela dépend des tes locales (cde : locale) et c’est normal, en Français il n’y a déjà pas de règles pour les caractères accentués, alors dans une langue étrangère aucune raison que cela corresponde à ce que tu imagines

Tu veux dire pas de règles algorithmiques? Car en classement alphabétique classique il y a un ordre.
Les caractères accentués ont un ordre qui est , pour la lettre e : e, é, è, ê, ë
Ce qui fait que l’oirdre donne pécher avant pêcher.

Note: lien pour plus de détail: http://dictionnaire.sensagent.leparisien.fr/Classement%20alphabétique/fr-fr/#Ligatures,_lettres_accentuées_et_majuscules

je reprends;
sur mon deb9 : tout est en « fr_FR.UTF-8 » , en particulier les « locale » sauf LC_ALL qui est vide
env |grep LC est vide
locale donne

LANG=fr_FR.UTF-8
LANGUAGE=
LC_CTYPE="fr_FR.UTF-8"
LC_NUMERIC="fr_FR.UTF-8"
LC_TIME="fr_FR.UTF-8"
LC_COLLATE="fr_FR.UTF-8"
LC_MONETARY="fr_FR.UTF-8"
LC_MESSAGES="fr_FR.UTF-8"
LC_PAPER="fr_FR.UTF-8"
LC_NAME="fr_FR.UTF-8"
LC_ADDRESS="fr_FR.UTF-8"
LC_TELEPHONE="fr_FR.UTF-8"
LC_MEASUREMENT="fr_FR.UTF-8"
LC_IDENTIFICATION="fr_FR.UTF-8"
LC_ALL=

sur mon deb10 :
env |grep LC donne

LC_ADDRESS=fr_FR.UTF-8
LC_NAME=fr_FR.UTF-8
LC_MONETARY=fr_FR.UTF-8
LC_PAPER=fr_FR.UTF-8
LC_IDENTIFICATION=fr_FR.UTF-8
LC_TELEPHONE=fr_FR.UTF-8
LC_MEASUREMENT=fr_FR.UTF-8
LC_TIME=fr_FR.UTF-8
LC_ALL=C
LC_NUMERIC=fr_FR.UTF-8

locale donne

LANG=fr_FR.UTF-8
LANGUAGE=
LC_CTYPE="C"
LC_NUMERIC="C"
LC_TIME="C"
LC_COLLATE="C"
LC_MONETARY="C"
LC_MESSAGES="C"
LC_PAPER="C"
LC_NAME="C"
LC_ADDRESS="C"
LC_TELEPHONE="C"
LC_MEASUREMENT="C"
LC_IDENTIFICATION="C"
LC_ALL=C

alors là je bloque,je m’attendais aux même résultats
il va falloir retourner dans les bouquins.

Ça me semble bien être la solution, non ?

jcsm33 a dit :

Ça me semble bien être la solution, non ?


Chez moi ça ne suffit pas (locale me donne le même résultat que dindoun en debian 9).
Pour simplifier je change un peu mon lili.txt en n’y mettant que des nombres entiers positifs ou nuls.

$ cat lili.txt
69 97 91 23 6
54 31 87 14 16
98 23 58 0 11
31 71 53 79 5
56 31 23 75 26
54 31 87 8 24
9 97 38 45 18
53 97 55 49 16
56 31 23 18 8
56 31 23 75 21
$ sort -n lili.txt
31 71 53 79 5
54 31 87 8 24
56 31 23 18 8
69 97 91 23 6
98 23 58 0 11
9 97 38 45 18
53 97 55 49 16
54 31 87 14 16
56 31 23 75 21
56 31 23 75 26

le résultat n’est pas celui attendu.

$ LC_ALL=C sort -n lili.txt
9 97 38 45 18
31 71 53 79 5
53 97 55 49 16
54 31 87 14 16
54 31 87 8 24
56 31 23 18 8
56 31 23 75 21
56 31 23 75 26
69 97 91 23 6
98 23 58 0 11

C’est déjà mieux mais les deux lignes commençant par 54 ne sont pas dans le bon ordre.
Par contre pour celles commençant par 56 c’est parfait.
Je ne comprends pas pourquoi le LC_ALL=C fait une telle différence alors qu’il ne s’agit
que de nombres entiers positifs. L’ordre des entiers ne fait-il pas l’objet d’un consensus international ?

LC_ALL=C sort -k1,5n lili.txt ne fait pas mieux que LC_ALL=C sort -n lili.txt

LC_ALL=C sort -k1n -k2n -k3n -k4n -k5n lili.txt

ou

sort -k1,1n -k2,2n -k3,3n -k4,4n -k5,5n lili.txt

donnent le bon résultat :

9 97 38 45 18
31 71 53 79 5
53 97 55 49 16
54 31 87 8 24
54 31 87 14 16
56 31 23 18 8
56 31 23 75 21
56 31 23 75 26
69 97 91 23 6
98 23 58 0 11

mais je préfère la seconde solution parce que je ne vois pas ce que les variables d’environnement auraient à faire là. Pour des caractères d’accord mais pour des nombres entiers ?
D’autre part c’est bien empirique, je ne suis pas sûr que cela marchera aussi bien sur un autre exemple.
Je vais essayer maintenant en mélangeant chaînes de caractères et entiers positifs.

Un ordre, mais plus de norme comme le précise un extrait de ton lien « Jusqu’en novembre 2010, le classement alphabétique était encadré en France par la norme AFNOR NF Z44-001. Cette norme a néanmoins été annulée, notamment en raison de l’informatisation des bases de données, à laquelle elle ne permettait pas de répondre de façon satisfaisante »

Je n’ai jamais creusé, mais cela pourrait lié à cela (extrait de https://fr.wikipedia.org/wiki/Alphabet_français)

En français, à la différence d’autres langues, les signes diacritiques ou les combinaisons de lettres (digrammes et ligatures) ne sont pas pris en compte dans l’ordre alphabétique primaire, ni dans les jeux de lettres (mots croisés, Scrabble, etc.) ; ces différences d’accents ou de ligatures sont prises en compte seulement au niveau ternaire, c’est-à-dire après le niveau secondaire (différences de casse), considéré plus important, et qui suit le classement alphabétique principal des mots selon les 26 classes de lettres.

2 J'aime

effectivement je confirme.
et le français n’est pas le seul à avoir le problème; l’espagnol a aussi ce genre de soucis, et toutes les langues utilisant des signes diacritiques à l’exception d’une langue, qui se pose en « maitre du monde »: l’anglais
Qui va bien avec le pays qui se considère aussi comme le maitre du monde, et pays majeur de l’informatique.

Où sont passées les lettres de la dernière colonne ?

C’est un peu « cliché » ce que tu nous dis là, il existe des mots en anglais avec des diacritiques, mais c’est juste qu’on ne les classe pas par ordre alphabétique.

jcsm33 a dit : « Où sont passées les lettres de la dernière colonne ? »

Je les ai enlevées pour montrer que même avec un tableau constitué de nombres entiers

j’ai des résultats que je ne comprends pas.