grepping fichiers binaires et UTF16
Standard grep
/pcregrep
etc. peut être facilement utilisé avec des fichiers binaires pour ASCII ou données UTF8 - est-il un moyen simple de les faire essayer UTF16 trop (de préférence simultanément, mais au lieu de cela le fera)?
Données que j'essaie de faire est tout ASCII de toute façon (les références dans les bibliothèques, etc.), il n'a tout simplement pas obtenir trouvé que parfois, il est 00 entre les deux personnages, et parfois il n'y en a pas.
Je ne vois pas de moyen de faire les choses du point de vue sémantique, mais ces 00s devrait faire l'affaire, sauf que je ne peut pas l'utiliser facilement sur la ligne de commande.
- ...ce n'est pas ASCII si les caractères à deux octets de long.
- Je veux dire, plage ASCII des caractères (U+0000 à U+007F), pas de codage ASCII.
Vous devez vous connecter pour publier un commentaire.
Le moyen le plus facile est de simplement convertir le fichier texte en utf-8 et le tuyau de grep:
J'ai essayé de faire le contraire (convertir ma requête de l'utf-16), mais il semble que grep n'aime pas cela. Je pense qu'il pourrait avoir à faire avec l'endianness, mais je ne suis pas sûr.
Il semble que grep va convertir une requête qui est de l'utf-16 pour de l'utf-8/ascii. Voici ce que j'ai essayé:
Si test.txt est utf-16 fichier cela ne fonctionne pas, mais il fonctionne si test.txt ascii. Je ne peux que conclure que la commande grep est la conversion de ma requête à l'ascii.
EDIT: Ici est vraiment fou de ce genre de travaux, mais ne vous donne pas beaucoup d'informations utiles:
Comment ça fonctionne? Eh bien, il convertit votre fichier hex (sans supplément de mise en forme que hexdump s'applique habituellement). Il les tuyaux que dans grep. Grep est à l'aide d'une requête qui est construit en se faisant l'écho de votre requête (sans saut de ligne) en fonction iconv qui la convertit en utf-16. C'est ensuite canalisé dans sed pour supprimer la NOMENCLATURE (les deux premiers octets de l'utf-16 fichier utilisé pour déterminer l'endianness). C'est ensuite canalisé dans hexdump de sorte que la requête et l'entrée sont les mêmes.
Malheureusement, je pense que ce sera à la fin de l'impression de l'ENSEMBLE du fichier si il y a un seul match. Aussi cela ne fonctionnera pas si l'utf-16 dans votre fichier binaire est stocké dans un autre boutisme de votre machine.
EDIT2: je l'Ai!!!!
Cette recherche la version hexadécimale du code de la chaîne
Test
(en utf-16) dans le fichiertest.txt
iconv
ne fonctionne pas, comme c'est un fichier binaire beaucoup de non-utf-16, eticonv
sorties sur la première erreur.pcregrep `echo -n "test" | iconv -f utf-8 -t utf-16le | hexdump -e '/1 "x%02x"' | sed 's/x/\\\\x/g'` <binary.file
. Plus important encore, il ne nécessite pas de l'utf-16 caractères sur 2 octets limite de quelque chose de toutes les méthodes précédentes avaient de gros problèmes avec. Fonctionne même avec-i
.Vous pouvez inclure explicitement les valeurs null (00s) dans la chaîne de recherche, bien que vous obtiendrez des résultats avec des valeurs nulles, de sorte que vous pouvez rediriger la sortie vers un fichier de sorte que vous pouvez regarder avec une raisonnable de l'éditeur, ou le tuyau à travers sed pour remplacer les valeurs null. De rechercher pour "barre" en *.utf16.txt:
Le "-P" raconte grep pour accepter de Perl syntaxe, qui permet \x00 de l'étendre à null, et l'un dit à ignorer le fait que l'Unicode ressemble binaire à elle.
-a
drapeau de la commande grep est la magie ici. en supposant que vous n'avez pas de gros fichiers à la recherche (dans ce cas, ce serait peut-être trop lent), vous pouvez la rendre un peu plus facile de taper simplement en spécifiant.
au lieu de\x00
. Le.
va correspondre à quoi que ce soit, et pas seulement une valeur null. Ce n'est pas toujours ce que vous voulez, mais probablement la plupart du temps sera beau. Souvent, le sed pour effacer les valeurs null n'est pas nécessaire, soit ils ne sont pas d'imprimer quoi que ce soit sur la production. Donc pour ton exemple, justegrep -a b.a.r *.utf16.txt
devrait fonctionner.grep: invalid UTF-8 byte sequence in input
...-P
option pour permettre la\xnn
. Je l'ai fait sans perl a été à l'aide de "." c'est à dire un seul char et comment @nirmal réponse ci-dessousJ'ai trouvé ci-dessous la solution qui a le mieux fonctionné pour moi, à partir de https://www.splitbits.com/2015/11/11/tip-grep-and-unicode/
Grep ne joue pas bien avec l'Unicode, mais il peut être contourné. Par exemple, pour trouver,
en UTF-16 fichier, utiliser une expression régulière pour ignorer le premier octet de chaque personnage,
Aussi, dites grep pour traiter le fichier en tant que texte, à l'aide de "- a", le final de la commande ressemble à ceci,
Je l'utiliser tout le temps après le dumping le registre de Windows que sa sortie est au format unicode. Ceci est en cours d'exécution sous Cygwin.
J'avais besoin de faire cela de façon récursive, et voici ce que j'ai trouvé:
C'est absolument horrible et très lent; j'en suis certain, il y a une meilleure façon et j'espère que quelqu'un peut l'améliorer, mais j'étais pressé 😛
Ce que les morceaux ne:
donne récursive liste de noms de fichier avec des chemins relatifs à courant
Boucle en Bash; pour chaque ligne de la liste des chemins d'accès aux fichiers, mettre le chemin en
$l
et de faire la chose dans la boucle. (Pourquoi j'ai utilisé une boucle shell au lieu de xargs, ce qui aurait été beaucoup plus rapide: j'ai besoin de préfixer chaque ligne de la sortie avec le nom du fichier en cours. Ne pouvais pas penser à une façon de le faire que si j'étais en train de nourrir plusieurs fichiers à la fois à iconv, et depuis que je vais faire un fichier à la fois, de toute façon, boucle shell est plus facile de syntaxe/s'échapper.)Convertir le fichier nommé dans
$l
: supposons que le fichier d'entrée est de l'utf-16 little-endian et le convertir en utf-8. Le-s
fait iconv se taire à propos de la conversion des erreurs (il y en aura beaucoup, parce que certains fichiers de cette structure de répertoire sont pas en utf-16). La sortie de cette conversion va vers stdout.C'est un hack:
nl
insère les numéros de ligne, mais il arrive à avoir une "utiliser cette chaîne de caractères arbitraire de séparer le numéro de la ligne" paramètre, donc j'ai mis le nom de fichier (suivi du côlon et de l'espace) dans que. Puis-je utilisercut
d'enlever le numéro de la ligne, en laissant seulement le préfixe de nom de fichier. (Pourquoi je n'ai pas utilisésed
: l'échappement est beaucoup plus facile de cette façon. Si j'ai utilisé une expression sed, j'ai à vous soucier de là l'expression régulière caractères dans les noms de fichiers, ce qui dans mon cas il y avait beaucoup de.nl
est beaucoup plus bête quesed
, et il suffit de prendre le paramètre-s
entièrement littéralement, et le shell gère l'échappement pour moi.)Donc, d'ici à la fin de ce pipeline, j'ai converti un tas de fichiers dans les lignes de l'utf-8, avec le préfixe du nom de fichier, que j'ai ensuite grep. Si il y a des matchs, je peux dire quel fichier ils sont dans le préfixe.
Mises en garde
grep -R
, parce que je suis frai une nouvelle copie deiconv
,nl
,cut
, etgrep
pour chaque fichier. C'est horrible.grep -R
ainsi que cette commande (et si vous avez plusieurs types de codage unicode, comme certains le big-endian et certaines little-endian fichiers, vous devez régler cette commande et l'exécuter à nouveau pour chaque codage différent).find . -type f
sur OS Xripgrep
Utilisation
ripgrep
utilitaire à grep UTF-16 fichiers.Exemple de syntaxe:
Pour vider toutes les lignes, exécutez:
rg -N . file
.Le sed déclaration est plus que je peux envelopper ma tête autour de. J'ai un simpliste, loin-de-parfait script TCL qui, je pense, fait un OK de travail avec mon point de test d'un:
J'ai ajouté ceci dans un commentaire de l'accepté la réponse ci-dessus, mais pour le rendre plus facile à lire. Cette option vous permet de rechercher du texte dans un tas de fichiers tout en affichant les noms de fichiers qu'il est de trouver le texte. Tous ces fichiers ont une .reg extension depuis que je suis à la recherche par le biais de exportés fichiers de Registre Windows. Il suffit de les remplacer .reg avec toute l'extension de fichier.
Vous pouvez utiliser les éléments suivants Ruby one-liner:
Pour des raisons de simplicité, il peut être défini comme la fonction shell comme:
Alors il être utilisé de la même façon que grep:
Source: Comment utiliser Ruby readlines.grep pour l'UTF-16 fichiers?