join: "Fichier 2 non trié"

13

J'ai deux fichiers _jeter3.txt et _jeter1.txt

J'ai vérifié qu'ils sont tous les deux triés sur la 20e colonne en utilisant sort -c

sort -t '     ' -c -k20,20 _jeter3.txt
sort -t '     ' -c -k20,20 _jeter1.txt
#no errors

mais il y a une erreur quand je veux les joindeux fichiers ça dit que le deuxième fichier n'est pas trié:

join -t '   ' -1 20 -2 20 _jeter1.txt _jeter3.txt > /dev/null
join: File 2 is not in sorted order

Je ne comprends pas pourquoi.

cat /etc/*-release #FYI
openSUSE 11.0 (i586)
VERSION = 11.0

MISE À JOUR : l'utilisation de ' sort -f' et join -i(les deux ne respectant pas la casse) corrige le problème. Mais cela n'explique pas mon problème initial.

UPDATE : versions de sort & join:

> join --version
join (GNU coreutils) 6.11
Copyright (C) 2008 Free Software Foundation, Inc.
(...)

> sort --version
sort (GNU coreutils) 6.11
Copyright (C) 2008 Free Software Foundation, Inc.
(...)
Pierre
la source
Pouvez-vous nous donner la sortie de "join --version" et "sort --version" juste par souci d'exhaustivité? Je ne peux pas obtenir d'anciennes versions de gnu join pour me donner ce message d'erreur en toute circonstance.
Bruce Ediger
3
Veuillez publier des exemples de données qui présentent le problème et la sortie de locale.
Gilles 'SO- arrête d'être méchant'

Réponses:

25

J'ai eu la même erreur avec Ubuntu 11.04, avec sortet les joindeux dans la version (GNU coreutils) 8.5.

Ils sont clairement incompatibles. En fait la sortcommande semble buggée: il n'y a pas de différence avec ou sans l' option -f( --ignore-case). Lors du tri, aaBc'est toujours avant aBa. Les caractères non alphanumériques semblent également toujours ignorés ( abcavant ab-x)

Join semble s'attendre à l'inverse ... Mais j'ai une solution

En fait, cela est lié à la séquence de classement: utiliser LANG=en_EN sort -k 1,1 <myfile> ...puis LANG=en_EN join ...élimine le message.

L'internationalisation est la racine du mal ... (personne ne le documente clairement).

Michael
la source
Donc, si les deux utilisent LANG=en_EN, cela fonctionnera certainement? Cela fonctionnera-t-il pour n'importe quel environnement local, tant que les deux utilisent le même environnement local? Pouvons-nous dire que la différence entre sortet joinest qu'ils utilisent une locale différente par défaut?
Aaron McDaid
L' -koption est-elle la réponse ici, ou est-ce la LANG=en_EN? On ne sait pas quelle est la solution exacte ici.
Utilisateur
5

Étiez-vous en train de trier avec des nombres? J'ai trouvé que le remplissage nul de la colonne que je rejoignais a résolu ce problème pour moi.

cat file.txt \
     | awk -F"   " '{ $20=sprintf("%06s", $20); print $0}' \
     | sort > readytojoin.txt
Conor
la source
5

Si vous êtes sûr d'avoir correctement trié vos fichiers d'entrée et que leurs lignes peuvent être associées, vous pouvez éviter l'erreur ci-dessus en exécutant join --nocheck-order file1.txt file2.txt

Yoav Weiss
la source
4

sort utilise par défaut la ligne entière comme clé

join utilise uniquement le champ spécifié comme clé.

Vous devez corriger cette incompatibilité en limitant le tri à utiliser uniquement la clé sur laquelle vous souhaitez vous connecter.

La page de manuel Join indique:

Important: FILE1 et FILE2 doivent être triés dans les champs de jointure. Par exemple, utilisez 'sort -k 1b, 1' si> 'join' n'a pas d'options. Notez que les comparaisons respectent les règles spécifiées par 'LC_COLLATE'. Si l'entrée> n'est pas triée et que certaines lignes ne peuvent pas être jointes, un message d'avertissement sera donné.

PeterVermont
la source
2
LOCALE=C sort ...
LOCALE=C join ...

Cela résoudra votre problème. Le problème, comme l'a souligné @Michael, est la séquence de classement, qui dépend de votre paramètre LOCALE.

Jignesh Smart
la source
2

Notez que si vous voyez cette erreur et que vous avez déjà trié sur une colonne spécifique et que vous vous battez la tête contre le mur, par exemple sort -k4,4, vous devrez peut-être également définir le séparateur pour la commande de tri

Apparemment, OP l'a déjà fait avec -t '' mais pour un texte normal séparé par des tabulations, je recommanderais

sort -t $'\t' ...

La commande sort peut incorporer des espaces comme séparateurs par défaut même sur quelque chose qui ressemble à un fichier séparé par des tabulations (surtout s'il y a des espaces à l'intérieur de la colonne sur laquelle vous effectuez le tri).

Ensuite, si vous avez transmis ces données triées à joindre, et que vous avez

join -t $'\t' ...

Ensuite, cela finit par provoquer le message d'erreur à ce sujet non trié. Comme indiqué ci-dessus, join peut ne pas accepter -t '' cependant.

Colin D
la source
1

Pour join l'argument après -t est un caractère. Pour le tri, vous pouvez fournir un séparateur de tri plus long. Je pense que vous pouvez joindre les fichiers sur un champ différent que vous souhaitez, et ignorer le cas résout le problème par coïncidence.

Et je suis d'accord avec Gilles, que des exemples de données seraient utiles.

Paweł Brodacki
la source