GNU/Linux >> Tutoriels Linux >  >> Linux

Utiliser Uniq sur le texte Unicode ?

Je souhaite supprimer les lignes en double d'un fichier contenant des mots en écriture syriaque. Le fichier source comporte 3 lignes, la 1ère et la 3ème sont identiques.

$ cat file.txt 
ܐܒܘܢ
ܢܗܘܐ
ܐܒܘܢ

Quand j'utilise sort et uniq , le résultat suppose que les 3 lignes sont identiques, ce qui est faux :

$ cat file.txt | sort | uniq -c
      3 ܐܒܘܢ

Définir explicitement les paramètres régionaux sur le syriaque n'aide pas non plus.

$ LC_COLLATE=syr_SY.utf8 cat file.txt | sort | uniq -c      
     3 ܐܒܘܢ

Pourquoi cela arriverait-il ?
J'utilise Kubuntu 18 et bash, si cela compte.

Réponse acceptée :

L'implémentation GNU de uniq comme trouvé sur Ubuntu, avec -c , ne signale pas le nombre de identiques contigus lignes mais compte les lignes contiguës qui trient de la même manière¹.

La plupart des locales internationales sur les systèmes GNU ont ce bogue que de nombreux caractères complètement indépendants ont été définis avec le même ordre de tri, la plupart d'entre eux parce que leur ordre de tri n'est pas défini du tout. La plupart des autres systèmes d'exploitation s'assurent que tous les caractères ont un ordre de tri différent.

$ expr ܐ = ܒ
1

(expr c'est = l'opérateur, pour les arguments qui ne sont pas numériques, renvoie 1 si les opérandes sont identiques, 0 sinon).

C'est la même chose avec ar_SY.UTF-8 ou en_GB.UTF-8 .

Ce dont vous auriez besoin, c'est d'un paramètre régional où ces caractères ont reçu un ordre de tri différent. Si Ubuntu avait des paramètres régionaux pour la langue syriaque, vous pourriez vous attendre à ce que ces caractères aient reçu un ordre de tri différent, mais Ubuntu n'a pas de tels paramètres régionaux.

Vous pouvez regarder la sortie de locale -a pour une liste des paramètres régionaux pris en charge. Vous pouvez activer plus de paramètres régionaux en exécutant dpkg-reconfigure locales en tant que root . Vous pouvez également définir plus de paramètres régionaux manuellement en utilisant localedef basé sur les fichiers de définition dans /usr/share/i18n/locales , mais vous n'y trouverez aucune donnée pour la langue syriaque.

Notez que dans :

LC_COLLATE=syr_SY.utf8 cat file.txt | sort | uniq -c

Vous définissez uniquement la variable LC_COLLATE pour le cat commande (qui n'affecte pas la façon dont elle affiche le contenu du fichier, cat ne se soucie pas de la collation ni même de l'encodage des caractères car ce n'est pas un utilitaire de texte). Vous voudriez le définir pour les deux sort et uniq . Vous souhaitez également définir LC_CTYPE vers une locale qui a un jeu de caractères UTF-8.

Comme votre système n'a pas syr_SY.utf8 locale, c'est la même chose que d'utiliser le C locale (la locale par défaut).

En fait, ici, les paramètres régionaux C ou C.UTF-8 sont probablement les paramètres régionaux que vous souhaitez utiliser.

Dans ces paramètres régionaux, l'ordre de classement est basé sur le point de code, le point de code Unicode pour C.UTF-8, la valeur d'octet pour C, mais cela finit par être le même car le codage de caractères UTF-8 a cette propriété.

$ LC_ALL=C expr ܐ = ܒ
0
$ LC_ALL=C.UTF-8 expr ܐ = ܒ
0

Donc avec :

(export LANG=ar_SY.UTF-8 LC_COLLATE=C.UTF-8 LANGUAGE=syr:ar:en
 unset LC_ALL
 sort <file | uniq -c)

Vous auriez un LC_CTYPE avec UTF-8 comme jeu de caractères, un ordre de classement basé sur le point de code et les autres paramètres pertinents pour votre région, donc par exemple des messages d'erreur en syriaque ou en arabe si GNU coreutils sort ou uniq les messages ont été traduits dans ces langues (ils ne l'ont pas encore fait).

Connexe :Comment marquer plusieurs contacts pour envoyer le même texte en tant que bcc - fonctionnalité qui existe sur Android ?

Si vous ne vous souciez pas de ces autres paramètres, c'est tout aussi simple (et aussi plus portable) à utiliser :

<file LC_ALL=C sort | LC_ALL=C uniq -c

Ou

(export LC_ALL=C; <file sort | uniq -c)

comme @isaac l'a déjà montré.


Linux
  1. sort Exemples de commandes sous Linux

  2. tri :commande introuvable

  3. Trier un fichier délimité par des tabulations

  4. Commande ou script Linux comptant les lignes dupliquées dans un fichier texte ?

  5. Obtenir une ligne spécifique à partir d'un fichier texte en utilisant uniquement un script shell

Utilisation du fichier de configuration SSH

Comment verrouiller un fichier texte sous Linux à l'aide de la commande flock

Comment :une introduction à l'utilisation de Git

Transférer des fichiers à l'aide de WinSCP

Rechercher et remplacer du texte dans un fichier entre une plage de lignes à l'aide de sed

Comment insérer du texte à la 1ère ligne d'un fichier à l'aide de sed ?