418 votes

Comment puis-je rechercher tous les caractères non ASCII ?

J'ai plusieurs fichiers XML très volumineux et j'essaie de trouver les lignes qui contiennent des caractères non ASCII. J'ai essayé ce qui suit :

grep -e "[\x{00FF}-\x{FFFF}]" file.xml

Mais cela renvoie chaque ligne du fichier, qu'elle contienne ou non un caractère dans la plage spécifiée.

La syntaxe est-elle fausse ou est-ce que je fais quelque chose de mal ? J'ai également essayé :

egrep "[\x{00FF}-\x{FFFF}]" file.xml 

(avec des guillemets simples et doubles entourant le motif).

0 votes

Les caractères ASCII ne font qu'un octet de long, donc à moins que le fichier soit unicode, il ne devrait pas y avoir de caractères au-dessus de 0xFF.

0 votes

Comment faire pour aller au-delà \xFF ? Grep donne une erreur "grep : range out of order in character class".

0 votes

Parfois, il est bon d'avoir un deuxième avis sur les personnages dont le bit haut est activé dans un fichier. Dans ce cas, j'aime tr <file.txt -d '\000-\177' >foo.out && ls -al foo.out pour obtenir un compte. Et/ou suivi de od -x foo.out pour avoir un aperçu des valeurs réelles.

573voto

jerrymouse Points 3510

Vous pouvez utiliser la commande :

grep --color='auto' -P -n "[\x80-\xFF]" file.xml

Cela vous donnera le numéro de ligne, et mettra en évidence les caractères non ASCII en rouge.

Dans certains systèmes, en fonction de vos paramètres, la méthode ci-dessus ne fonctionnera pas, vous pouvez donc grep par l'inverse

grep --color='auto' -P -n "[^\x00-\x7F]" file.xml

Notez également que l'élément important est le -P qui équivaut à --perl-regexp : il interprétera donc votre motif comme une expression régulière Perl. Il est également indiqué que

ceci est hautement expérimental et grep -P peut avertir de l'absence d'implémentation. non implémentées.

52 votes

Cela ne fonctionnera pas sous BSD grep (sur OS X 10.8 Mountain Lion), car il ne prend pas en charge l'option P option.

21 votes

Pour mettre à jour mon dernier commentaire, la version GNU de grep est disponible dans l'application Homebrew dupes (activer l'utilisation de brew tap homebrew/dupes ) : brew install grep

54 votes

@BastiaanVanDeWeerd a raison, grep sous OSX 10.8 ne prend plus en charge PCRE ("expressions régulières compatibles avec Perl") car Darwin utilise désormais BSD grep au lieu de GNU grep. Une alternative à l'installation du dupes est d'installer pcre à la place : brew install pcre ... dans ce cadre, vous obtiendrez les éléments suivants pcregrep que vous pouvez utiliser comme suit : pcregrep --color='auto' -n "[\x80-\xFF]" file.xml

153voto

pvandenberk Points 1199

Au lieu de faire des hypothèses sur la plage d'octets des caractères non ASCII, comme le font la plupart des solutions ci-dessus, il est légèrement préférable pour l'OMI d'être explicite sur la plage d'octets réelle des caractères ASCII.

La première solution, par exemple, serait donc la suivante :

grep --color='auto' -P -n '[^\x00-\x7F]' file.xml

(qui recherche tout caractère en dehors de la plage hexadécimale ASCII : de \x00 jusqu'à \x7F )

Sur Mountain Lion, cela ne fonctionne pas (en raison de l'absence de support PCRE dans BSD grep) mais avec pcre installé via Homebrew, ce qui suit fonctionnera tout aussi bien :

pcregrep --color='auto' -n '[^\x00-\x7F]' file.xml

Y a-t-il des avantages ou des inconvénients auxquels quelqu'un peut penser ?

10 votes

Cela a fonctionné pour moi là où les solutions précédentes ont échoué. Trouver les apostrophes de M$ Word n'a jamais été aussi facile !

5 votes

Si vous avez un shell compatible avec bash mais que pcre-grep ne fonctionne pas, LC_COLLATE=C grep $'[^\1-\177]' fonctionne (pour les fichiers sans octets nuls)

2 votes

Cette solution semble fonctionner de manière plus cohérente que les solutions ci-dessus.

68voto

Thelema Points 2697

Ce qui suit fonctionne pour moi :

grep -P "[\x80-\xFF]" file.xml

Les caractères non ASCII commencent à 0x80 et vont jusqu'à 0xFF lorsqu'on regarde les octets. Grep (et sa famille) ne fait pas de traitement Unicode pour fusionner les caractères multi-octets en une seule entité pour la correspondance regex comme vous semblez le vouloir. Le site -P dans mon grep permet l'utilisation de \xdd dans les classes de caractères pour obtenir ce que vous voulez.

1 votes

Pour ceux qui ne savent pas immédiatement comment appeler cette fonction sur plusieurs fichiers, il suffit d'exécuter : find . -nom *.xml | xargs grep -P "[ \x80 - \xFF ]"

1 votes

Cela renvoie une correspondance, mais il n'y a aucune indication sur ce qu'est le personnage et où il se trouve. Comment voir ce qu'est le caractère et où il se trouve ?

0 votes

L'ajout du "-n" donnera le numéro de ligne, les caractères non visibles seront affichés comme un bloc dans le terminal : grep -n -P "[ \x80 - \xFF ]" file.xml

65voto

Gilles Points 37537

Le moyen le plus simple est de définir un caractère non-ASCII... comme un caractère qui n'est pas un caractère ASCII.

LC_ALL=C grep '[^ -~]' file.xml

Ajouter un onglet après le ^ si nécessaire.

Réglage de LC_COLLATE=C évite les mauvaises surprises concernant la signification des plages de caractères dans de nombreux pays. Réglage de LC_CTYPE=C est nécessaire pour faire correspondre des caractères d'un seul octet - sinon la commande manquerait des séquences d'octets invalides dans le codage actuel. Réglage de LC_ALL=C évite complètement les effets dépendants de la localisation.

1 votes

Sur RedHat 6.4 avec tcsh, j'ai dû utiliser << env LC_COLLATE=C grep -n '[^ -~]' file.xml >>. J'ai ajouté -n pour obtenir le numéro de ligne.

0 votes

Pour moi echo "A" | LC_COLLATE=C grep '[^ -~]' renvoie une correspondance

0 votes

@frabjous Il ne devrait pas. Quels sont vos autres paramètres linguistiques (sortie de locale ) ? Sur quelle plateforme ?

62voto

noquery Points 492

En perl

perl -ane '{ if(m/[[:^ascii:]]/) { print  } }' fileName > newFile

1 votes

Sous OSX10.11, j'ai dû essayer plusieurs solutions grep+regex avant de trouver cette solution qui fonctionne réellement.

0 votes

Vous pouvez partager cette solution OSX avec nous !

0 votes

Le perl script ci-dessus est la solution dont je parle.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X