Ich habe einige Datenbank-Dumps von einem Windows-System auf meiner Box. Sie sind Textdateien. Ich benutze Cygwin, um sie zu durchsuchen. Dies scheinen reine Textdateien zu sein. Ich öffne sie mit Texteditoren wie Notepad und Wordpad und sie sehen gut lesbar aus. Wenn ich grep auf sie starte, wird es jedoch sagen binary file foo.txt matches
.
Ich habe festgestellt, dass die Dateien einige ASCII- NUL
Zeichen enthalten, die meines Erachtens Artefakte aus dem Datenbank-Dump sind.
Warum betrachtet grep diese Dateien als binär? Der NUL
Charakter? Gibt es eine Flagge im Dateisystem? Was muss ich ändern, damit grep mir die Zeilenübereinstimmungen anzeigt?
--null-data
kann nützlich sein, wennNUL
das Trennzeichen ist.Antworten:
Wenn
NUL
sich irgendwo in der Datei ein Zeichen befindet, betrachtet grep es als Binärdatei.Möglicherweise gibt es eine solche Problemumgehung
cat file | tr -d '\000' | yourgrep
, um zuerst alle Nullen zu entfernen und dann die Datei zu durchsuchen.quelle
-a
/--text
, zumindest mit GNU grep.NUL
schneidet jede übereinstimmende Zeile zuerst ab (wahrscheinlich, weil es Cs printf aufruft und ihm die übereinstimmende Zeile gibt?). Auf einem solchen System gibt agrep cmd .sh_history
so viele leere Zeilen zurück, wie es Zeilen gibt, die mit 'cmd' übereinstimmen, da jede Zeile von sh_history ein bestimmtes Format mit einemNUL
am Anfang jeder Zeile hat. (Aber Ihr Kommentar "zumindest zu GNU grep" wird wahrscheinlich wahr. Ich habe momentan keinen zur Hand, um ihn zu testen, aber ich gehe davon aus, dass sie damit gut umgehen)grep
unter Cygwin als binär eingestuft wurde, da sie einen langen Bindestrich (0x96) anstelle eines regulären ASCII-Bindestrichs / Minus (0x2d) enthielt. Ich denke, diese Antwort hat das Problem des OP gelöst, aber es scheint, dass es unvollständig ist.grep -a
arbeitete für mich:quelle
Sie können die Verwendung
strings
Dienstprogramm , um den Textinhalt aus einer beliebigen Datei zu extrahieren und dann lenke sie durchgrep
, wie folgt aus :strings file | grep pattern
.quelle
GNU grep 2.24 RTFS
Schlussfolgerung: Nur 2 und 2 Fälle:
NUL
, z.Bprintf 'a\0' | grep 'a'
Codierungsfehler nach C99
mbrlen()
, zB:da
\x80
kann nicht das erste Byte eines UTF-8-Unicode-Punkts sein: UTF-8 - Beschreibung | en.wikipedia.orgDarüber hinaus, wie von Stéphane Chazelas erwähnt. Warum betrachtet grep eine Datei als binär? | Unter Unix und Linux Stack Exchange werden diese Überprüfungen nur bis zum ersten Puffer mit der Länge TODO durchgeführt.
Nur bis zum ersten Puffer gelesen
Wenn also ein NUL- oder Codierungsfehler in der Mitte einer sehr großen Datei auftritt, wird diese möglicherweise trotzdem abgegriffen.
Ich stelle mir das aus Performancegründen vor.
ZB: Dies druckt die Zeile:
aber das tut nicht:
Die tatsächliche Puffergröße hängt davon ab, wie die Datei gelesen wird. ZB vergleichen:
Mit dem
sleep
wird die erste Zeile an grep übergeben, auch wenn sie nur 1 Byte lang ist, da der Prozess in den Ruhezustand wechselt und der zweite Lesevorgang nicht prüft, ob die Datei binär ist.RTFS
Finden Sie heraus, wo die stderr-Fehlermeldung codiert ist:
Führt uns zu
/src/grep.c
:Wenn diese Variablen gut benannt wären, wären wir im Grunde genommen zu dem Schluss gekommen.
encoding_error_output
Das schnelle Greifen nach
encoding_error_output
zeigt, dass der einzige Codepfad , der ihn ändern kann, durchläuftbuf_has_encoding_errors
:dann eben
man mbrlen
.nlines_first_null und nlines
Initialisiert als:
Wenn also eine Null gefunden
0 <= nlines_first_null
wird , wird sie wahr.TODO wann kann
nlines_first_null < nlines
jemals falsch sein? Ich bin faul geworden.POSIX
Definiert keine binären Optionen grep - Durchsucht eine Datei nach einem Muster | pubs.opengroup.org und GNU grep dokumentieren dies nicht, daher ist RTFS der einzige Weg.
quelle
(printf '\n\0y') | grep y
mit(printf '\n'; sleep 1; printf '\0y') | grep y
zum Beispiel.export LC_CTYPE='en_US.UTF-8'
wie in meinem Beispiel oder etwas anderes? Buf las: erstaunliches Beispiel, hinzugefügt, um zu antworten. Sie haben offensichtlich die Quelle mehr als ich lesen, erinnert mich an jenem Hacker koans :-) „Der Student aufgeklärten war“Eine meiner Textdateien wurde plötzlich von grep als binär angesehen:
Lösung war, es zu konvertieren, indem man verwendet
iconv
:quelle
0xFC
hexadezimal, also außerhalb des Bereichs, den grep für utf8 (bis zu0x7F
) erwarten würde . Prüfen Sie mit printf 'a \ x7F' | grep 'a' wie Ciro oben beschreibt.Die Datei
/etc/magic
oder/usr/share/misc/magic
hat eine Liste von Sequenzen, die der Befehlfile
zur Bestimmung des Dateityps verwendet.Beachten Sie, dass die Binärdatei möglicherweise nur eine Ersatzlösung ist. Manchmal werden auch Dateien mit ungewöhnlicher Codierung als binär betrachtet.
grep
Unter Linux gibt es einige Optionen, um Binärdateien wie--binary-files
oder zu verarbeiten-U / --binary
quelle
mbrlen()
. Beispiel und Quelleninterpretation unter: unix.stackexchange.com/a/276028/32558Einer meiner Schüler hatte dieses Problem. Es ist ein Fehler
grep
inCygwin
. Wenn die Datei nicht-ASCII - Zeichen hat,grep
undegrep
es als binäres sehen.quelle
Wenn Sie die Frage "Warum betrachtet grep eine Datei als binär?" Beantworten, können Sie Folgendes verwenden
iconv
:In meinem Fall gab es spanische Zeichen, die in Texteditoren korrekt angezeigt wurden, aber von grep als binär betrachtet wurden.
iconv
Die Ausgabe wies mich auf die Zeilen- und Spaltennummern dieser Zeichen hinIm Fall von
NUL
Zeicheniconv
werden diese als normal betrachtet und nicht gedruckt, sodass diese Methode nicht geeignet istquelle
Ich hatte das gleiche problem Früher
vi -b [filename]
habe ich die hinzugefügten Zeichen gesehen. Ich habe die Steuerzeichen^@
und gefunden^M
. Geben Sie dann in vi ein:1,$s/^@//g
, um die^@
Zeichen zu entfernen . Wiederholen Sie diesen Befehl für^M
.Warnung: Um die "blauen" Steuerzeichen zu erhalten, drücken Sie Ctrl+ und vdann Ctrl+ Moder Ctrl+ @. Dann speichern und beenden Sie vi.
quelle