tr beklagt sich über "Illegal byte sequence"

24

Ich bin brandneu in UNIX und benutze Kirk McElhearns "The Mac OS X Command Line", um mir einige Befehle beizubringen.

Ich versuche, zu verwenden trund grepdamit ich nach Textzeichenfolgen in einem regulären MS-Office Word-Dokument suchen kann.

$ tr '\r' '\n' < target-file | grep search-string

Aber alles, was es zurückgibt, ist:

Illegal byte sequence.

robomechanoid:Position-Paper-Final-Draft robertjralph$ tr '\r' '\n' < Position-Paper-Final-Version.docx | grep DeCSS
tr: Illegal byte sequence
robomechanoid:Position-Paper-Final-Draft robertjralph$ 

Ich habe tatsächlich die gleiche Zeile in einem Skript ausgeführt, das ich erstellt habe, viund es führt die Suche korrekt aus.

user74886
quelle
Ich kann nicht verstehen, warum ich mich beschweren würde. Haben Sie dasselbe eingegeben, wie Sie es in der Frage angegeben haben? grep findet nicht was Sie wollen, xdoc ist ein schlecht definierter Standard. Niemand weiß wirklich, was in diesen Dateien steht, die Leute haben es rückgängig gemacht, anscheinend war der Standard keine Hilfe.
Strg-Alt-Delor

Antworten:

29

grepist ein Textverarbeitungswerkzeug. Es erwartet, dass ihre Eingabe Textdateien sind . Es scheint, dass das gleiche gilt für trMacOS (obwohl trBinärdateien unterstützt werden sollen).

Computer speichern Daten als Folgen von Bytes . Ein Text ist eine Folge von Zeichen. Es gibt verschiedene Möglichkeiten, Zeichen als Bytes zu kodieren, sogenannte Zeichenkodierungen . Die De-facto-Standard-Zeichenkodierung in den meisten Ländern der Welt, insbesondere unter OSX, ist UTF-8 , eine Kodierung für den Unicode- Zeichensatz. Es gibt nur 256 mögliche Bytes, aber über eine Million mögliche Unicode-Zeichen, sodass die meisten Zeichen als Mehrfachbytes codiert werden. UTF-8 ist eine Kodierung mit variabler Länge: Je nach Zeichen kann die Kodierung eines Zeichens ein bis vier Bytes dauern. Einige Folgen von Bytes repräsentieren in UTF-8 kein Zeichen. Daher gibt es Folgen von Bytes, die keine gültigen UTF-8-Textdateien sind.

trbeklagt sich, weil es auf eine solche Bytefolge gestoßen ist. Es wird erwartet, dass eine in UTF-8 codierte Textdatei angezeigt wird, es werden jedoch Binärdaten angezeigt, die nicht in UTF-8 gültig sind.

Ein Microsoft Word-Dokument ist keine Textdatei, sondern ein Textverarbeitungsdokument. Textverarbeitungsdokumentformate codieren nicht nur Text, sondern auch Formatierungen, eingebettete Bilder usw. Das Word-Format ist wie die meisten Textverarbeitungsformate keine Textdatei.

Sie können Textverarbeitungstools anweisen, Byte zu verarbeiten, indem Sie das Gebietsschema ändern . Wählen Sie speziell das Gebietsschema "C" aus, was im Grunde genommen "nichts Besonderes" bedeutet. In der Befehlszeile können Sie Gebietsschemaeinstellungen mit Umgebungsvariablen auswählen .

export LC_CTYPE=C
tr '\r' '\n' < target-file | grep search-string

Dies wird keinen Fehler auslösen, aber es wird auch nichts Sinnvolles tun, da target-filees sich immer noch um eine Binärdatei handelt, die wahrscheinlich nicht die meisten von Ihnen angegebenen Suchzeichenfolgen enthält.

Dies tr '\r' '\n'ist im Übrigen kein sehr nützlicher Befehl, es sei denn, Sie haben Textdateien von Mac OS 9 oder älter übrig. \r(Zeilenumbruch) war in Mac OS vor Mac OS X das Trennzeichen für \nZeilenumbrüche. Seit OS X ist das Trennzeichen für Zeilenumbrüche (Zeilenvorschub, Unix-Standard) und Textdateien enthalten keine Zeilenumbrüche. Windows verwendet die zweistellige Sequenz CR-LF, um Zeilenumbrüche darzustellen. tr -d '\r'würde eine Windows-Textdatei in eine Unix / Linux / OSX-Textdatei konvertieren.

Wie können Sie also in einem Word-Dokument über die Befehlszeile suchen? Ein .docxWord-Dokument ist eigentlich ein Zip-Archiv, das mehrere Dateien enthält, von denen sich die wichtigsten in XML befinden .

unzip -l Position-Paper-Final-Version.docx

Mac OS X enthält das Dienstprogramm zipgrep zum Durchsuchen von ZIP-Dateien.

zipgrep DeCSS Position-Paper-Final-Version.docx

Das Ergebnis wird nicht sehr gut lesbar sein, da XML-Dateien im docx-Format meist aus einer großen Zeile bestehen. Wenn Sie im Haupttext des Dokuments suchen möchten, extrahieren Sie die Datei word/document.xmlaus dem Archiv. Beachten Sie, dass diese Datei zusätzlich zum Dokumenttext ein XML-Markup enthält, das die Struktur des Dokuments darstellt. Sie können das XML-Markup ein wenig massieren sed, um es in überschaubare Zeilen aufzuteilen.

unzip -p Position-Paper-Final-Version.docx word/document.xml |
sed -e 's/></>\n</g' |
grep DeCSS
Gilles 'SO - hör auf böse zu sein'
quelle
1
+1 für eine gute Zusammenfassung und zusätzliche Bits. Eines muss ich allerdings sagen. Um die XML zu formatieren, können Sie xml_ppsie in einem Paket xml-twig-toolsunter Debian Gnu + Linux verwenden (ich kenne keinen Mac).
Strg-Alt-Delor
2
In Excel für Mac 2011 werden CSV-Dateien mit \ r Zeilenenden gespeichert, sodass dieser Aufruf tatsächlich sehr relevant und nützlich ist.
Noah Yetter
1
Wie Outlook für Mac 2011, wenn Sie eine tabulatorgetrennte Kontaktliste exportieren.
Ivan X
1
Nun, ich habe nicht genug Reputation, um dies abzulehnen, aber diese Antwort ist absolut falsch. Es beginnt mit " trErwarten [...] Sie, dass ihre Eingabe Textdateien sind."; In der POSIX-Spezifikation heißt es eindeutig: "Die Standardeingabe kann ein beliebiger Dateityp sein." . Bitte korrigieren Sie Ihre Antwort.
7heo.tk
@ 7heo.tk „diese Antwort ist völlig falsch“ ist eine grobe Übertreibung, aber du hast recht, trist angeblich Binäreingang zu verarbeiten (insbesondere es zu null Prozess angenommen hat , Bytes korrekt). POSIX gibt jedoch nicht eindeutig an, wie mit Eingaben umgegangen werden soll, die keine Zeichenfolge sind. (Wenn ich ein Implementierer wäre, würde ich ungültige Byte-Sequenzen unverändert durchgehen (oder sie mit entfernen -s) und einen Fehler beim Standard-Komitee melden.) Offensichtlich beschwert sich macOS's tr über sie.
Gilles 'SO- hör auf böse zu sein'
13

Ich nehme an, dass Ihr Charmap aus den Gebietsschemas UTF-8 ist, so dass Sie Probleme mit Binärdateien haben. Wechseln Sie einfach zum Gebietsschema C:

LC_ALL=C tr '\r' '\n' < target-file | LC_ALL=C grep search-string
vinc17
quelle
Sie können Klammern verwenden, um zu vermeiden, dass die Sprache zweimal angegeben wird. LC_ALL=C ( tr '\r' '\n' < target-file | grep search-string ). Das Dokument ist jedoch nicht C-lokal. Ist utf16 und gezippt und komplex und jedermanns Vermutung. Ich würde so aussehen, als ob ich ein Tool verwende, das es in ein anderes Format konvertieren kann, das Sie zB html oder odt verarbeiten können (odt ist ebenfalls gezippt, aber gut definiert und einfach zu interpretieren).
Strg-Alt-Delor
1
Die Syntax mit den Klammern (Klammern) funktioniert nicht bei allen Shells (nicht bash, nicht zsh, nicht dash). Dann, in Bezug auf die MS Word-Datei, kommt es darauf an. Ich habe einige solche Dateien, in denen der stringsBefehl Klartext gibt.
Vinc17
Alternativ ( export LC_ALL=C; tr '\r' '\n' < target-file | grep search-string; )sollte funktionieren.
Vinc17
1
stringshat Superkräfte: Es kann Dateien lesen, die nicht nur aus UTF-8 oder ASCII-Text bestehen.
Strg-Alt-Delor
Tut ()mir leid wegen der Sache, von der ich dachte, dass sie funktionieren würde, danke an @ vinc17 für eine Lösung.
Strg-Alt-Delor