Wie grep ich eine Textdatei, die einige Binärdaten enthält?


121

grep kehrt zurück

Die Binärdatei test.log stimmt überein

Beispielsweise

echo    "line1 re \x00\r\nline2\r\nline3 re\r\n" > test.log  # in zsh
echo -e "line1 re \x00\r\nline2\r\nline3 re\r\n" > test.log  # in bash
grep re test.log

Ich wünschte, das Ergebnis würde Zeile 1 und Zeile 3 (insgesamt zwei Zeilen) anzeigen.

Ist es möglich tr, die nicht druckbaren Daten in lesbare Daten umzuwandeln, damit grep wieder funktioniert?


Bitte beachten Sie, dass es ein Programm gibt, das Binärzeichen aus einer Binärdatei herausfiltert und nur die Textzeichen (lesbar) behält. Hier: soft.tahionic.com/download-words_extractor/index.html
InTheNameOfScience

Entschuldigung, aber ... fehlen Sie nicht -eim echoBefehl?
Sopalajo de Arrierez

Wenn Sie 'zsh' verwenden, ist es ohne -e in Ordnung. Wenn Sie 'bash' verwenden, sollten Sie '-e' hinzufügen.
Daniel YC Lin

Antworten:


67

Sie können die Datendatei cat -vz

$ cat -v tmp/test.log | grep re
line1 re ^@^M
line3 re^M

die dann weiter nachbearbeitet werden könnte, um den Müll zu entfernen; Dies ist am analogsten zu Ihrer Abfrage zur Verwendung trfür die Aufgabe.


5
Mein Problem gelöst. Vielen Dank! Hier ist, was über man catsagt -v:-v, --show-nonprinting use ^ and M- notation, except for LFD and TAB
tommy.carstensen

Beachten Sie, dass dies auch in einer Pipeline funktioniert. ZBset | cat -v | grep variable
Funroll

1
Warum dies verwenden, wenn grep --text funktioniert? Das scheint viel komplexer zu sein.
Michael Haefele

grep --textfunktioniert nicht immer; es respektiert STRG + D als Datei-Terminator. Wenn Sie das in Ihrer Binärdatei haben, wird grep vorzeitig beendet.
Tommy


91

Eine Möglichkeit besteht darin, Binärdateien ohnehin einfach als Text zu behandeln. grep --textDies kann jedoch dazu führen, dass Binärinformationen an Ihr Terminal gesendet werden. Das ist keine gute Idee, wenn Sie ein Terminal verwenden, das den Ausgabestream interpretiert (z. B. VT / DEC oder viele andere).

Alternativ können Sie Ihre Datei trmit dem folgenden Befehl senden :

tr '[\000-\011\013-\037\177-\377]' '.' <test.log | grep whatever

Dadurch wird weniger als ein Leerzeichen (außer Zeilenumbruch) und mehr als 126 in ein .Zeichen umgewandelt, wobei nur die Ausdrucke übrig bleiben .


Wenn Sie möchten, dass jedes "illegale" Zeichen durch ein anderes ersetzt wird, können Sie das folgende C-Programm verwenden, einen klassischen Standardeingabefilter:

#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;
}

Dies gibt Ihnen an {{NN}}, wo NNsich der Hex-Code für das Zeichen befindet. Sie können das einfach printffür jeden gewünschten Ausgabestil anpassen .

Sie können dieses Programm hier in Aktion sehen, wo es:

pax$ printf 'Hello,\tBob\nGoodbye, Bob\n' | ./filterProg
Hello,{{09}}Bob
Goodbye, Bob

Diese Methode ordnet alle binären Zeichen demselben '.' Zu. Symbol. Gibt es eine andere Methode, um sie lesbaren Symbolen zuzuordnen?
Daniel YC Lin

Sicher, Sie können es über ein anderes Filterprogramm ausführen, von dem ich eines in einem Update bereitgestellt habe.
Paxdiablo

1
Ich denke tr '[:cntrl:] '.'ist besser. Und es sollte \000-\010\013\014\016-\037\177-\377'in Ihrer tr-Syntax sein.
Daniel YC Lin

2
Nach dem Testen, tr '[\000-\010\013\014\016-\037\177-\377]' '_'funktionsfähig, ist die cntrl nicht für meinen Fall geeignet.
Daniel YC Lin

2
Sie können den catSchritt speichern , indem Sie grep --textin trstatt umgekehrt einleiten. Auf diese Weise können Sie auch mehrere Dateien durchsuchen und die Dateinamenreferenz in der Ausgabe beibehalten.
aaaantoine

33

Sie können beispielsweise "Zeichenfolgen" verwenden, um Zeichenfolgen aus einer Binärdatei zu extrahieren

strings binary.file | grep foo

Funktionierte gut für mich, da die Quelle ein Debug-Protokoll mit UID in jeder Zeile war. Vielen Dank.
mbrownnyc

hat auch bei mir gut funktioniert. Danke für deine Antwort. Rettete meinen Tag :)
Shekhar

2
Ich schätze die Antwort von @paxdiablo, aber für eine schnelle Antwort und die Arbeit können Sie nichts auszusetzen haben.
Wil

Ich habe versucht, eine paxdiablo-Lösung zu verwenden, aber sie hat mir keine der erwarteten Ergebnisse gebracht. @moodywoody Ihre Lösung ist schnell, einfach und gibt genau das aus, was ich brauchte!
Justinhartman

20

Sie können grep zwingen, Binärdateien anzuzeigen mit:

grep --binary-files=text

Vielleicht möchten Sie auch -o( --only-matching) hinzufügen, damit Sie nicht Tonnen von binärem Kauderwelsch erhalten, der Ihr Terminal belastet.


Möglicherweise wird binärer Müll ausgegeben, der böse Nebenwirkungen haben kann, wenn es sich bei der Ausgabe um ein Terminal handelt und der Terminaltreiber einige davon als Befehle interpretiert.
Daniel YC Lin

Wenn Sie verwenden --only-matchingund Ihr regulärer Ausdruck nicht mit beliebigen Binärdaten übereinstimmt, haben Sie kein Problem.
AB

Wenn der reguläre Ausdruck 'first. * end' ist und die Binärdaten das Muster '. *' enthalten, kann der Prozess für meine Nachbearbeitung nicht korrigiert werden. Trotzdem danke.
Daniel YC Lin

16

Ab Grep 2.21 werden Binärdateien unterschiedlich behandelt :

Bei der Suche nach Binärdaten kann grep jetzt Nicht-Text-Bytes als Zeilenabschluss behandeln. Dies kann die Leistung erheblich steigern.

Was jetzt passiert, ist, dass bei Binärdaten alle Nicht-Text-Bytes (einschließlich Zeilenumbrüche) als Zeilenabschlüsse behandelt werden. Wenn Sie dieses Verhalten ändern möchten, können Sie:

  • verwenden --text. Dadurch wird sichergestellt, dass nur Zeilenumbrüche Leitungsabschlusszeichen sind

  • verwenden --null-data. Dadurch wird sichergestellt, dass nur Nullbytes Zeilenabschlusszeichen sind


5

grep -a erzwingt die Suche und Ausgabe von grep aus einer Datei, die grep für binär hält. grep -a re test.log



2

du kannst tun

strings test.log | grep -i

Dadurch wird die Ausgabe von give als lesbare Zeichenfolge in grep konvertiert.


0

Sie können auch das Word Extractor- Tool ausprobieren . Word Extractor kann mit jeder Datei auf Ihrem Computer verwendet werden, um die Zeichenfolgen, die menschlichen Text / Wörter enthalten, vom Binärcode (exe-Anwendungen, DLLs) zu trennen.


In meinem Fall benötige ich keinen Wortextraktor, ich muss die Zeilennummer behalten.
Daniel YC Lin

0

Folgendes habe ich in einem System verwendet, in dem der Befehl "strings" nicht installiert war

cat yourfilename | tr -cd "[:print:]"

Dies druckt den Text und entfernt nicht druckbare Zeichen auf einen Schlag, im Gegensatz zu "cat -v filename", bei dem eine Nachbearbeitung erforderlich ist, um unerwünschte Inhalte zu entfernen. Beachten Sie, dass einige der Binärdaten möglicherweise druckbar sind, sodass Sie immer noch etwas Kauderwelsch zwischen den guten Sachen bekommen. Ich denke, Strings entfernen auch diesen Kauderwelsch, wenn Sie das verwenden können.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.