GNU/Linux >> Tutoriels Linux >  >> Linux

Linux - Comment rendre Tr conscient des caractères non ascii (unicode) ?

J'essaie de supprimer certains caractères du fichier (UTF-8). J'utilise tr à cet effet :

tr -cs '[[:alpha:][:space:]]' ' ' <testdata.dat 

Le fichier contient des caractères étrangers (comme "Латвийская" ou "àé"). tr ne semble pas les comprendre :il les traite comme non alpha et les supprime également.

J'ai essayé de modifier certains de mes paramètres régionaux :

LC_CTYPE=C LC_COLLATE=C tr -cs '[[:alpha:][:space:]]' ' ' <testdata.dat
LC_CTYPE=ru_RU.UTF-8 LC_COLLATE=C tr -cs '[[:alpha:][:space:]]' ' ' <testdata.dat
LC_CTYPE=ru_RU.UTF-8 LC_COLLATE=ru_RU.UTF-8 tr -cs '[[:alpha:][:space:]]' ' ' <testdata.dat

Malheureusement, rien de tout cela n'a fonctionné.

Comment puis-je faire tr comprendre Unicode ?

Réponse acceptée :

C'est une limitation connue (1, 2, 3, 4, 5, 6) de l'implémentation GNU de tr .

Ce n'est pas tant qu'il ne prend pas en charge foreign , des caractères non anglais ou non ASCII, mais qu'il ne prend pas en charge les caractères multi-octets.

Ces caractères cyrilliques seraient traités correctement, s'ils étaient écrits dans le jeu de caractères iso8859-5 (un seul octet par caractère) (et que vos paramètres régionaux utilisaient ce jeu de caractères), mais votre problème est que vous utilisez UTF-8 où non-ASCII les caractères sont encodés sur 2 octets ou plus.

GNU a un plan (voir aussi) pour résoudre ce problème et le travail est en cours mais pas encore là.

FreeBSD ou Solaris tr n'ont pas le problème.

En attendant, pour la plupart des cas d'utilisation de tr , vous pouvez utiliser GNU sed ou GNU awk qui prennent en charge les caractères multi-octets.

Par exemple, votre :

tr -cs '[[:alpha:][:space:]]' ' '

pourrait s'écrire :

gsed -E 's/( |[^[:space:][:alpha:]])+/ /'

ou :

gawk -v RS='( |[^[:space:][:alpha:]])+' '{printf "%s", sep $0; sep=" "}'

Pour convertir entre minuscules et majuscules (tr '[:upper:]' '[:lower:]' ):

gsed 's/[[:upper:]]/l&/g'

(que l est un L minuscule , pas le 1 chiffre).

ou :

gawk '{print tolower($0)}'

Pour la portabilité, perl est une autre alternative :

perl -Mopen=locale -pe 's/([^[:space:][:alpha:]]| )+/ /g'
perl -Mopen=locale -pe '$_=lc$_'

Si vous savez que les données peuvent être représentées dans un jeu de caractères à un octet, vous pouvez les traiter dans ce jeu de caractères :

(export LC_ALL=ru_RU.iso88595
 iconv -f utf-8 |
   tr -cs '[:alpha:][:space:]' ' ' |
   iconv -t utf-8) < Russian-file.utf8

Linux
  1. Comment rendre un ancien ordinateur utile à nouveau

  2. Comment s'assurer qu'une application continue de fonctionner sous Linux

  3. Comment écrire des caractères non ASCII en utilisant echo ?

  4. Deux versions de python sous Linux. comment faire de 2.7 la valeur par défaut

  5. Comment créer un package de test Travis CI pour Linux, OS X, Windows ?

Comment rendre un fichier exécutable sous Linux

Comment créer une clé USB multiboot sous Linux et Windows

Comment Linux peut vous faciliter la vie

Comment supprimer les caractères (^M) d'un fichier sous Linux

Comment rendre un fichier exécutable dans un terminal Linux ?

Comment créer un serveur Minecraft sur des distributions Linux