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).
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.
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?
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.
En perl
perl -ane '{ if(m/[[:^ascii:]]/) { print } }' fileName > newFile
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.
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
.
le code suivant fonctionne:
find /tmp | perl -ne 'print if /[^[:ascii:]]/'
remplacer /tmp
par le nom du répertoire que vous souhaitez consulter.
é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 }' '{}' \;
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
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'