tr lamenta "Sequenza di byte illegali"


24

Sono nuovo di zecca per UNIX e sto usando "La riga di comando di Mac OS X" di Kirk McElhearn per insegnarmi alcuni comandi.

Sto tentando di utilizzare tre in grepmodo da poter cercare stringhe di testo in un normale documento Word di MS-Office.

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

Ma tutto ciò che restituisce è:

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$ 

Ho effettivamente eseguito la stessa riga su uno script che ho creato vie fa la ricerca correttamente.


Non riesco a capire perché tr si lamenterebbe, hai digitato lo stesso che hai posto nella domanda? grep non troverà quello che vuoi, xdoc è uno standard mal definito. Nessuno sa davvero cosa ci sia in quei file, le persone lo hanno progettato al contrario, apparentemente lo standard non è stato di alcun aiuto.
ctrl-alt-delor

Risposte:


29

grepè uno strumento di elaborazione del testo. Si aspetta che il loro input sia un file di testo . Sembra che lo stesso valga per trmacOS (anche se trsi suppone che supporti i file binari).

I computer memorizzano i dati come sequenze di byte . Un testo è una sequenza di caratteri. Esistono diversi modi per codificare i caratteri come byte, chiamati codifiche dei caratteri . La codifica dei caratteri standard di fatto nella maggior parte del mondo, specialmente su OSX, è UTF-8 , che è una codifica per il set di caratteri Unicode . Esistono solo 256 byte possibili, ma oltre un milione di possibili caratteri Unicode, quindi la maggior parte dei caratteri sono codificati come più byte. UTF-8 è una codifica di lunghezza variabile: a seconda del carattere, possono essere necessari da uno a quattro byte per codificare un carattere. Alcune sequenze di byte non rappresentano alcun carattere in UTF-8. Pertanto, esistono sequenze di byte che non sono file di testo UTF-8 validi.

trsi lamenta perché ha riscontrato una tale sequenza di byte. Si aspetta di vedere un file di testo codificato in UTF-8, ma vede dati binari che non sono UTF-8 validi.

Un documento di Microsoft Word non è un file di testo: è un documento di elaborazione testi. I formati di documenti di elaborazione testi codificano non solo il testo, ma anche la formattazione, le immagini incorporate, ecc. Il formato di Word, come la maggior parte dei formati di elaborazione di testi, non è un file di testo.

È possibile indicare agli strumenti di elaborazione del testo di operare sui byte modificando le impostazioni internazionali . In particolare, selezionare la locale "C", che in pratica significa "niente di speciale". Sulla riga di comando, è possibile scegliere le impostazioni locali con le variabili di ambiente .

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

Ciò non genererà alcun errore, ma non farà nulla di utile poiché target-fileè ancora un file binario che probabilmente non contiene la maggior parte delle stringhe di ricerca specificate.

Per inciso, tr '\r' '\n'non è un comando molto utile a meno che non siano rimasti file di testo da Mac OS 9 o precedenti. \r(ritorno a capo) era il separatore di nuova riga in Mac OS prima di Mac OS X. Dal momento che OSX, il separatore di nuova riga è \n(avanzamento riga, lo standard unix) e i file di testo non contengono ritorni a capo. Windows utilizza la sequenza di due caratteri CR-LF per rappresentare le interruzioni di riga; tr -d '\r'converte un file di testo di Windows in un file di testo Unix / Linux / OSX.

Quindi, come puoi cercare in un documento Word dalla riga di comando? Un .docxdocumento Word è in realtà un archivio zip contenente diversi file, i principali sono in XML .

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

Mac OS X include l' utilità zipgrep per cercare all'interno dei file zip.

zipgrep DeCSS Position-Paper-Final-Version.docx

Il risultato non sarà molto leggibile perché i file XML in formato docx sono costituiti principalmente da una riga enorme. Se si desidera cercare all'interno del testo principale del documento, estrarre il file word/document.xmldall'archivio. Si noti che oltre al testo del documento, questo file contiene markup XML che rappresenta la struttura del documento. Puoi massaggiare un po 'il markup XML sedper dividerlo in righe gestibili.

unzip -p Position-Paper-Final-Version.docx word/document.xml |
sed -e 's/></>\n</g' |
grep DeCSS

1
+1 per un buon riepilogo e bit extra. Ho una cosa da dire però. Per formattare l'xml, puoi usarlo xml_ppnel pacchetto xml-twig-toolssu Debian Gnu + Linux (non conosco un mac).
ctrl-alt-delor,

2
Excel per Mac 2011 salva i file CSV con terminazioni di riga, quindi questa invocazione tr è in effetti abbastanza pertinente e utile.
Noah Yetter,

1
Come Outlook per Mac 2011 quando esporti un elenco di contatti delimitati da tabulazioni.
Ivan X,

1
Bene, non ho abbastanza reputazione per sottovalutare questo, ma questa risposta è assolutamente errata. Si inizia con " tr[...] aspettarsi che il loro input sia un file di testo."; mentre la specifica POSIX afferma chiaramente "L'input standard può essere qualsiasi tipo di file". . Per favore, correggi la tua risposta.
7heo.tk,

@ 7heo.tk “questa risposta è assolutamente corretto” è un'esagerazione lordo, ma hai ragione, trsi suppone per elaborare l'input binario (in particolare, si suppone di processo nullo byte correttamente). POSIX, tuttavia, non specifica chiaramente in che modo deve gestire l'input che non è una sequenza di caratteri. (Se fossi un implementatore, passerei sequenze di byte non valide attraverso non modificate (o rimuoverle con -s), e solleverebbe un difetto con il comitato standard.) Evidentemente, macOS si lamenta di loro.
Gilles 'SO- smetti di essere malvagio' il

13

Suppongo che la tua charmap dalle impostazioni locali sia UTF-8, quindi avrai problemi con i file binari. Passa alla locale C:

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

puoi usare le parentesi quadre per evitare di specificare due volte la lingua. LC_ALL=C ( tr '\r' '\n' < target-file | grep search-string ). Comunque il docx non è C locale. Is è utf16 e zippato e complesso e la supposizione di chiunque. Sembrerei utilizzare uno strumento che può convertirlo in un formato diverso che è possibile elaborare, ad esempio html o odt (odt è anche zippato, ma ben definito e facile da interpretare).
ctrl-alt-delor

1
La sintassi con le parentesi (parentesi) non funziona con tutte le shell (non bash, non zsh, non trattino). Quindi, per quanto riguarda il file MS Word, dipende. Ho alcuni di questi file in cui il stringscomando fornisce un testo chiaro.
vinc17,

In alternativa, ( export LC_ALL=C; tr '\r' '\n' < target-file | grep search-string; )dovrebbe funzionare.
vinc17,

1
stringsha superpoteri: può leggere file che non sono solo testo utf-8 o ascii.
ctrl-alt-delor

Mi dispiace per la ()cosa che pensavo avrebbe funzionato, grazie a @ vinc17 per una correzione.
ctrl-alt-delor
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.