Comment grep un fichier texte qui contient des données binaires?
Grep renvoie
Binary file test.log matches
Par exemple
echo "line1 re x00rnline2rnline3 rern" > test.log # in zsh
echo -e "line1 re x00rnline2rnline3 rern" > test.log # in bash
grep re test.log
Je souhaite que le résultat montre line1 et line3 (total deux lignes).
Est-il possible d'utiliser tr
Convertir les données non imprimables en données lisibles, pour laisser grep fonctionner à nouveau?
10 réponses
Vous pouvez exécuter le fichier de données via cat -v
, par exemple
$ cat -v tmp/test.log | grep re
line1 re ^@^M
line3 re^M
Qui pourrait ensuite être post-traité pour supprimer les pourriels; ceci est plus analogue à votre requête sur l'utilisation de tr
pour la tâche.
Une façon est de simplement traiter les fichiers binaires comme du texte de toute façon, avec grep --text
mais cela peut bien entraîner l'envoi d'informations binaires à votre terminal. Ce n'est pas vraiment une bonne idée si vous utilisez un terminal qui interprète le flux de sortie (comme VT/DEC ou bien d'autres).
Vous pouvez également envoyer votre fichier via tr
avec la commande suivante:
tr '[\000-\011\013-\037\177-\377]' '.' <test.log | grep whatever
Cela changera tout ce qui est inférieur à un caractère d'espace (sauf newline) et tout ce qui est supérieur à 126, en un .
caractère, ne laissant que les printables.
Si vous voulez que chaque caractère" illégal " soit remplacé par un caractère différent, vous pouvez utiliser quelque chose comme le programme C suivant, un filtre d'entrée standard classique:
#include<stdio.h>
int main (void) {
int ch;
while ((ch = getchar()) != EOF) {
if ((ch == '\n') || ((ch >= ' ') && (ch <= '~'))) {
putchar (ch);
} else {
printf ("{{%02x}}", ch);
}
}
return 0;
}
Cela vous donnera {{NN}}
, où NN
est le code hexadécimal du caractère. Vous pouvez simplement ajuster le printf
pour le style de sortie que vous voulez.
Vous pouvez voir ce programme en action ici, où il:
pax$ printf 'Hello,\tBob\nGoodbye, Bob\n' | ./filterProg
Hello,{{09}}Bob
Goodbye, Bob
Vous pouvez utiliser" strings " pour extraire des chaînes d'un fichier binaire, par exemple
strings binary.file | grep foo
Vous pouvez forcer grep à regarder les fichiers binaires avec:
grep --binary-files=text
Vous pouvez également ajouter -o
(--only-matching
) donc, vous n'obtenez pas des tonnes de charabia binaire qui va bork votre terminal.
À partir de Grep 2.21, les fichiers binaires sont traités différemment :
Lors de la recherche de données binaires, grep peut maintenant traiter les octets non textuels comme ligne terminateur. Cela peut augmenter considérablement les performances.
Donc, ce qui se passe maintenant, c'est qu'avec les données binaires, tous les octets non textuels (y compris les nouvelles lignes) sont traités comme des terminaisons de ligne. Si vous voulez changer cela comportement, vous pouvez:
Utiliser
--text
. Cela garantira que seules les nouvelles lignes sont en ligne les terminateurs-
Utiliser
--null-data
. Cela garantira que seuls les octets nuls sont des terminateurs de ligne
Comme James Selvakumar l'a déjà dit, grep -a
fait l'affaire. -A ou -- text force Grep à gérer le flux d'entrée en tant que texte.
Voir la page de manuel http://unixhelp.ed.ac.uk/CGI/man-cgi?grep
Essayez
cat test.log | grep -a somestring
Vous pouvez faire
strings test.log | grep -i
Cela convertira la sortie give sous forme de chaîne lisible en grep.
Grep-a forcera grep à rechercher et à sortir à partir d'un fichier que grep pense binaire. grep-un nouveau test.log
Vous pouvez également essayer l'Outil Word Extractor . Word Extractor peut être utilisé avec n'importe quel fichier de votre ordinateur pour séparer les chaînes contenant du texte / des mots humains du code binaire (applications exe, DLL).