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 toutes les lignes du fichier, que la ligne contienne ou non un caractère dans la plage spécifiée.
La syntaxe est-elle incorrecte ou est-ce que je fais autre chose de mal? J'ai aussi essayé:
egrep "[\x{00FF}-\x{FFFF}]" file.xml
(avec des guillemets simples et doubles entourant le motif).
Réponses:
Vous pouvez utiliser la commande:
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, ce qui précède ne fonctionnera pas, vous pouvez donc grep par l'inverse
Notez également que le bit important est le
-P
drapeau qui équivaut à--perl-regexp
: il interprétera donc votre modèle comme une expression régulière Perl. Il dit également quela source
grep
(sur OS X 10.8 Mountain Lion), car il ne prend pas en charge l'P
option.grep
est disponible dans ladupes
bibliothèque de Homebrew (activer à l'aidebrew tap homebrew/dupes
):brew install grep
dupes
bibliothèque est d'installer à lapcre
place:brew install pcre
... dans le cadre de cela, vous obtiendrez l'pcregrep
utilitaire, que vous pouvez utiliser comme suit:pcregrep --color='auto' -n "[\x80-\xFF]" file.xml
brew
utilisateurs de Mac , les coreutils de GNU peuvent être installés avecbrew install coreutils
. Cela vous donnera beaucoup d'outils GNU préfixés par un «g» - dans ce cas, utilisezggrep
. Cela devrait éviter les problèmes liés au remplacement d'un utilitaire système, car les scripts Mac spécifiques au système dépendent désormais de grep BSD.ag "[\x80-\xFF]" file
vous avez juste besoin d'installerthe_silver_searcher
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 que l'OMI soit explicite sur la plage d'octets réelle des caractères ASCII.
Ainsi, la première solution par exemple deviendrait:
(qui recherche essentiellement tout caractère en dehors de la plage ASCII hexadécimale: de \ x00 à \ x7F)
Sur Mountain Lion, cela ne fonctionnera pas (en raison du manque de prise en charge PCRE dans BSD grep) , mais avec
pcre
installé via Homebrew, les éléments suivants fonctionneront tout aussi bien:Des avantages ou des inconvénients auxquels tout le monde peut penser?
la source
LC_COLLATE=C grep $'[^\1-\177]'
fonctionne (pour les fichiers sans octets nuls)Ce qui suit fonctionne pour moi:
Les caractères non ASCII commencent à 0x80 et vont à 0xFF lorsque vous regardez les octets. Grep (et la famille) ne fait pas de traitement Unicode pour fusionner des caractères multi-octets en une seule entité pour la correspondance regex comme vous semblez le vouloir. L'
-P
option dans mon grep permet d'utiliser des\xdd
échappements dans les classes de caractères pour accomplir ce que vous voulez.la source
echo '소녀시대' | grep -P "[\x80-\xFF]"
je ne retourne rien pour moi - quelqu'un d'autre peut-il confirmer? (GNU grep 2.21)echo '소녀시대' | grep -P "[^\x00-\x7F]"
. Ou utilisez simplementthe_silver_searcher
comme indiqué par @slf:echo '소녀시대' | ag "[\x80-\xFF]"
En perl
la source
perl -lne 'print if /[^[:ascii:]]/' file.xml
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.
Ajoutez un onglet après le
^
si nécessaire.Le réglage
LC_COLLATE=C
évite les mauvaises surprises sur la signification des plages de caractères dans de nombreux paramètres régionaux. Le réglageLC_CTYPE=C
est nécessaire pour faire correspondre les caractères à un octet - sinon la commande manquerait des séquences d'octets invalides dans le codage actuel. Le réglageLC_ALL=C
évite complètement les effets locaux.la source
echo "A" | LC_COLLATE=C grep '[^ -~]'
retourne un matchLC_ALL=en_US.UTF-8
, cela l'emporte sur leLC_COLLATE
paramètre. Vous ne devriez pas avoir cela dans votre environnement!LC_ALL
consiste uniquement à forcer une tâche spécifique à utiliser un environnement local particulier, généralementC
. Pour définir les paramètres régionaux par défaut pour toutes les catégories, définissezLANG
.LC_ALL=C
, il se comporte différemment sur Mac OS X et Ubuntu. Après avoir ajouté ce paramètre, ils donnent le même résultat.Voici une autre variante que j'ai trouvée qui a produit des résultats complètement différents de la recherche grep
[\x80-\xFF]
dans la réponse acceptée. Il sera peut-être utile à quelqu'un de trouver des caractères non ascii supplémentaires:grep --color='auto' -P -n "[^[:ascii:]]" myfile.txt
Remarque: le grep de mon ordinateur (un Mac) n'avait pas d'
-P
option, donc je l'ai faitbrew install grep
et j'ai commencé l'appel ci-dessus avecggrep
au lieu degrep
.la source
Le code suivant fonctionne:
Remplacez
/tmp
par le nom du répertoire que vous souhaitez rechercher.la source
Recherche de caractères non imprimables. TLDR; Résumé
LC_ALL=C
nécessaire pour que grep fasse ce que vous attendez avec unicode étenduSO les trouveurs de caractères non ascii préférés:
comme dans la première réponse, la grep inverse:
comme dans la première réponse mais AVEC
LC_ALL=C
:. . plus . . détail atroce à ce sujet:. . .
Je suis d'accord avec Harvey ci-dessus enterré dans les commentaires, il est souvent plus utile de rechercher des caractères non imprimables OU il est facile de penser non ASCII alors que vous devriez vraiment penser non imprimable. Harvey suggère "utilisez ceci:"
[^\n -~]
". Ajoutez \ r pour les fichiers texte DOS. Cela se traduit par"[^\x0A\x020-\x07E]
"et ajoutez \ x0D pour CR"De plus, l'ajout de -c (afficher le nombre de modèles correspondants) à grep est utile lors de la recherche de caractères non imprimables car les chaînes correspondantes peuvent perturber le terminal.
J'ai trouvé que l'ajout de la plage 0-8 et 0x0e-0x1f (à la plage 0x80-0xff) est un modèle utile. Cela exclut le TAB, le CR et le LF et un ou deux autres caractères imprimables rares. Donc, à mon humble avis, un modèle de grep assez utile (quoique brut) est celui-ci:
RÉELLEMENT, vous devrez généralement faire ceci:
panne:
Exemple d'utilisation pratique de find pour grep tous les fichiers du répertoire courant:
Vous pouvez parfois ajuster le grep. Par exemple, le caractère BS (0x08 - backspace) utilisé dans certains fichiers imprimables ou pour exclure VT (0x0B - onglet vertical). Les caractères BEL (0x07) et ESC (0x1B) peuvent également être considérés comme imprimables dans certains cas.
MISE À JOUR: J'ai dû revoir cela récemment. Et, YYMV en fonction des paramètres du terminal / des prévisions météorologiques solaires MAIS. . J'ai remarqué que grep ne trouvait pas beaucoup de caractères unicode ou étendus. Même si intuitivement, ils doivent correspondre à la plage 0x80 à 0xff, les caractères unicode à 3 et 4 octets ne correspondent pas. ??? Quelqu'un peut-il expliquer cela? OUI. @frabjous a demandé et @calandoa a expliqué que cela
LC_ALL=C
devrait être utilisé pour définir les paramètres régionaux pour que la commande fasse correspondre grep.par exemple, mes paramètres régionaux sont
LC_ALL=
videsgrep avec
LC_ALL=
vide correspond à des caractères codés sur 2 octets mais pas codés sur 3 et 4 octets:grep with
LC_ALL=C
semble correspondre à tous les caractères étendus que vous souhaitez:CETTE correspondance perl (partiellement trouvée ailleurs sur stackoverflow) OU l'inverse grep sur la réponse du haut semble trouver TOUS les caractères ~ bizarre ~ et ~ merveilleux ~ "non-ascii" sans définir les paramètres régionaux:
SO les trouveurs de caractères non ascii préférés:
comme dans la première réponse, la grep inverse:
comme dans la première réponse mais AVEC
LC_ALL=C
:la source
Étrangement, je devais le faire aujourd'hui! J'ai fini par utiliser Perl parce que je ne pouvais pas faire fonctionner grep / egrep (même en mode -P). Quelque chose comme:
Pour les caractères unicode (comme
\u2212
dans l'exemple ci-dessous), utilisez ceci:la source
Il pourrait être intéressant de savoir comment rechercher un caractère unicode. Cette commande peut vous aider. Il vous suffit de connaître le code en UTF8
la source
La recherche de tous les caractères non-ascii donne l'impression que l'on recherche des chaînes unicode ou a l'intention de supprimer lesdits caractères individuellement.
Pour les premiers, essayez l'un d'eux (la variable
file
est utilisée pour l'automatisation):Le grep de vanille ne fonctionne pas correctement sans LC_ALL = C comme indiqué dans les réponses précédentes.
La plage ASCII est
x00-x7F
, l'espace estx20
, puisque les chaînes ont des espaces, la plage négative l'omet.La plage non ASCII est
x80-xFF
, puisque les chaînes ont des espaces, la plage positive l'ajoute.La chaîne est présumée être au moins 7 caractères consécutifs dans la plage.
{7,}
.Pour une sortie lisible par le shell,
uchardet $file
renvoie une estimation du codage du fichier qui est passé à iconv pour une interpolation automatique.la source
uchardet
commande. Merci pour cet avertissement!