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

j'ai plusieurs très gros fichiers XML 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 retourne chaque ligne dans le fichier, indépendamment du fait que la ligne contient ou non un caractère dans la plage spécifiée.

est-ce que la syntaxe est erronée ou est-ce que je fais autre chose de mal? J'ai aussi essayé:

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

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

301
demandé sur kenorb 2010-06-09 00:48:13

10 réponses

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, le ci-dessus ne fonctionnera pas, de sorte que vous pouvez grep par l'inverse

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

Notez aussi que le bit important est le drapeau -P qui équivaut à --perl-regexp : il interprétera donc votre motif comme une expression régulière Perl. Il a également dit que

c'est très expérimental et grep -P peut prévenir de non-application caractéristique.

414
répondu jerrymouse 2017-03-09 14:54:33

au lieu de faire des suppositions au sujet de la gamme byte de caractères non ASCII, comme la plupart des solutions ci-dessus le font, il est légèrement préférable IMO d'être explicite au sujet de la gamme byte réelle de caractères ASCII à la place.

ainsi la première solution par exemple deviendrait:

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

(qui est essentiellement greps pour tout caractère en dehors de la gamme ASCII hexadécimale: de \x00 à \x7F)

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

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

les avantages ou les inconvénients que n'importe qui peut le penser?

100
répondu pvandenberk 2012-12-04 12:25:41

les travaux suivants pour moi:

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

les caractères Non ASCII commencent à 0x80 et vont à 0xFF en regardant les octets. Grep (et la famille) ne font pas le traitement Unicode pour fusionner des caractères multi-octets dans une entité unique pour l'appariement regex comme vous semblez vouloir. L'option -P dans mon grep permet l'utilisation de \xdd s'échappe dans les classes de caractères pour accomplir ce que vous voulez.

66
répondu Thelema 2010-06-08 21:59:22

En perl

perl -ane '{ if(m/[[:^ascii:]]/) { print  } }' fileName > newFile
46
répondu noquery 2013-02-10 14:05:58

la manière simple est de définir un caractère non-ASCII... comme un personnage qui n'est pas un personnage ASCII.

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

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

Setting LC_COLLATE=C évite les mauvaises surprises sur la signification des gammes de caractères dans de nombreux endroits. Définir LC_CTYPE=C est nécessaire pour faire correspondre des caractères à un octet-sinon la commande manquerait des séquences d'octets invalides dans l'encodage courant. Paramètre LC_ALL=C évite tout effet dépendant de la localisation.

34
répondu Gilles 2015-12-15 13:03:04

Voici une autre variante que j'ai trouvé qui a produit complètement résultats différents de la recherche grep pour [\x80-\xFF] dans la réponse acceptée. Peut-être sera-t-il utile à quelqu'un de trouver d'autres caractères non ascii:

grep --color='auto' -P -n "[^[:ascii:]]" myfile.txt

Note: le grep de mon ordinateur (un Mac) n'avait pas l'option -P , donc j'ai fait brew install grep et j'ai commencé l'appel ci-dessus avec ggrep au lieu de grep .

19
répondu ryanm 2016-03-23 17:00:21

le code suivant fonctionne:

find /tmp | perl -ne 'print if /[^[:ascii:]]/'

remplacer /tmp par le nom du répertoire que vous souhaitez consulter.

6
répondu user7417071 2017-01-13 23:02:41

étrangement, j'ai dû faire ça aujourd'hui! J'ai fini par utiliser Perl parce que je ne pouvais pas faire fonctionner grep/egrep (même en mode in-P). Quelque chose comme:

cat blah | perl -en '/\xCA\xFE\xBA\xBE/ && print "found"'

pour les caractères unicode (comme \u2212 dans l'exemple ci-dessous) utilisez ceci:

find . ... -exec perl -CA -e '$ARGV = @ARGV[0]; open IN, $ARGV; binmode(IN, ":utf8"); binmode(STDOUT, ":utf8"); while (<IN>) { next unless /\N{U+2212}/; print "$ARGV: $&: $_"; exit }' '{}' \;
1
répondu dty 2012-07-16 12:51:39

recherche de caractères non imprimables.

je suis d'accord avec Harvey ci-dessus enterré dans les commentaires, il est souvent plus utile de rechercher les caractères non-imprimables OU il est facile de penser la non-ASCII lorsque vous devriez vraiment penser à la non-imprimable. Harvey suggère "utilisez ceci: "[^\n -~]". Ajouter \R pour les fichiers texte DOS. Cela se traduit par "[^\x0A\x020 - \x07E] "et ajouter \x0D pour CR "

aussi, ajouter-c (show count of patterns matched) à grep est utile lors de la recherche de caractères non-imprimables car les chaînes de caractères matched peuvent perturber le terminal.

j'ai trouvé que l'ajout de la gamme 0-8 et 0x0e-0x1f (à la gamme 0x80-0xff) est un modèle utile. Cela exclut L'onglet, CR et LF et un ou deux autres caractères imprimables peu communs. Donc, IMHO un tout à fait utile (bien que brut) grep patron est celui-ci:

grep -c -P -n "[\x00-\x08\x0E-\x1F\x80-\xFF]" *

de rupture:

\x00-\x08 - non-printable control chars 0 - 7 decimal
\x0E-\x1F - more non-printable control chars 14 - 31 decimal
\x80-1xFF - non-printable chars > 128 decimal
-c - print count of matching lines instead of lines
-P - perl style regexps

Instead of -c you may prefer to use -n (and optionally -b) or -l
-n, --line-number
-b, --byte-offset
-l, --files-with-matches

E. G. exemple pratique d'utilisation pour grep tous les fichiers du répertoire courant:

find . -type f -exec grep -c -P -n "[\x00-\x08\x0E-\x1F\x80-\xFF]" {} + 

vous pouvez ajuster le grep à l'occasion. par exemple BS(0x08 - backspace) char utilisé dans certains fichiers imprimables ou pour exclure VT (0x0b-vertical tab). Les caractères BEL(0x07) et ESC(0x1B) peuvent également être considérés comme imprimables dans certains cas.

Non-Printable ASCII Chars
** marks PRINTABLE but CONTROL chars that is useful to exclude sometimes
Dec   Hex Ctrl Char description           Dec Hex Ctrl Char description
0     00  ^@  NULL                        16  10  ^P  DATA LINK ESCAPE (DLE)
1     01  ^A  START OF HEADING (SOH)      17  11  ^Q  DEVICE CONTROL 1 (DC1)
2     02  ^B  START OF TEXT (STX)         18  12  ^R  DEVICE CONTROL 2 (DC2)
3     03  ^C  END OF TEXT (ETX)           19  13  ^S  DEVICE CONTROL 3 (DC3)
4     04  ^D  END OF TRANSMISSION (EOT)   20  14  ^T  DEVICE CONTROL 4 (DC4)
5     05  ^E  END OF QUERY (ENQ)          21  15  ^U  NEGATIVE ACKNOWLEDGEMENT (NAK)
6     06  ^F  ACKNOWLEDGE (ACK)           22  16  ^V  SYNCHRONIZE (SYN)
7     07  ^G  BEEP (BEL)                  23  17  ^W  END OF TRANSMISSION BLOCK (ETB)
8     08  ^H  BACKSPACE (BS)**            24  18  ^X  CANCEL (CAN)
9     09  ^I  HORIZONTAL TAB (HT)**       25  19  ^Y  END OF MEDIUM (EM)
10    0A  ^J  LINE FEED (LF)**            26  1A  ^Z  SUBSTITUTE (SUB)
11    0B  ^K  VERTICAL TAB (VT)**         27  1B  ^[  ESCAPE (ESC)
12    0C  ^L  FF (FORM FEED)**            28  1C  ^\  FILE SEPARATOR (FS) RIGHT ARROW
13    0D  ^M  CR (CARRIAGE RETURN)**      29  1D  ^]  GROUP SEPARATOR (GS) LEFT ARROW
14    0E  ^N  SO (SHIFT OUT)              30  1E  ^^  RECORD SEPARATOR (RS) UP ARROW
15    0F  ^O  SI (SHIFT IN)               31  1F  ^_  UNIT SEPARATOR (US) DOWN ARROW
1
répondu gaoithe 2017-09-21 12:42:27

Il pourrait être intéressant de savoir comment rechercher un caractère unicode. Cette commande peut vous aider. Vous n'avez besoin de connaître le code QU'en UTF8

grep -v $'\u200d'
0
répondu arezae 2017-01-13 23:19:11