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?

Daniel YC Lin
quelle
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
serverfault.com/questions/328101/…
Ciro Santilli 法轮功 冠状 冠状 病. 事件 4.

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.

vielmetti
quelle
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
109
grep -a

Einfacher geht es nicht.

James Selvakumar
quelle
3
Dies ist das gleiche, grep --textwas paxdiablo 2 Jahre zuvor erwähnt hat
user829755
4
Ja, außer dass dies unter OSX nur funktioniert, wenn Sie Folgendes tun:LC_ALL="C" grep -a
Chris Stratton
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
paxdiablo
quelle
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
Moodywoody
quelle
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.

AB
quelle
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

Steven Penny
quelle
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

Kevin Buchs
quelle
3

Wie James Selvakumar bereits sagte, grep -amacht er den Trick. -a oder --text zwingt Grep, den Eingabestream als Text zu behandeln. Siehe Manpage http://unixhelp.ed.ac.uk/CGI/man-cgi?grep

Versuchen

cat test.log | grep -a somestring
DerKnorr
quelle
2

du kannst tun

strings test.log | grep -i

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

Mrid
quelle
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.

MattCollW
quelle
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.

Muurder
quelle