tr reclama de "Sequência ilegal de bytes"

24

Sou novato no UNIX e estou usando "A linha de comando do Mac OS X" de Kirk McElhearn para aprender alguns comandos.

Estou tentando usar tre greppara procurar cadeias de texto em um documento normal do MS-Office Word.

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

Mas tudo o que retorna é:

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$ 

Na verdade, eu executei a mesma linha em um script que eu criei vie faz a pesquisa corretamente.

user74886
fonte
Não vejo por que tr reclamaria. Você digitou o mesmo que fez na pergunta? O grep não encontrará o que você deseja, o xdoc é um padrão mal definido. Ninguém realmente sabe o que há nesses arquivos, as pessoas fizeram a engenharia reversa, aparentemente o padrão não ajudou em nada.
CTRL-ALT-DELOR

Respostas:

29

grepé uma ferramenta de processamento de texto. Ele espera que sua entrada seja um arquivo de texto . Parece que o mesmo vale para o trmacOS (embora trdeva suportar arquivos binários).

Os computadores armazenam dados como sequências de bytes . Um texto é uma sequência de caracteres. Existem várias maneiras de codificar caracteres como bytes, chamados codificações de caracteres . A codificação de caracteres padrão de fato na maior parte do mundo, especialmente no OSX, é UTF-8 , que é uma codificação para o conjunto de caracteres Unicode . Existem apenas 256 bytes possíveis, mas mais de um milhão de caracteres Unicode possíveis; portanto, a maioria dos caracteres é codificada como vários bytes. UTF-8 é uma codificação de tamanho variável: dependendo do caractere, pode levar de um a quatro bytes para codificar um caractere. Algumas seqüências de bytes não representam nenhum caractere em UTF-8. Portanto, existem seqüências de bytes que não são arquivos de texto UTF-8 válidos.

trestá reclamando porque encontrou uma sequência de bytes. Ele espera ver um arquivo de texto codificado em UTF-8, mas vê dados binários que não são válidos em UTF-8.

Um documento do Microsoft Word não é um arquivo de texto: é um documento de processamento de texto. Os formatos de documento de processamento de texto codificam não apenas texto, mas também formatação, imagens incorporadas etc. O formato do Word, como a maioria dos formatos de processamento de texto, não é um arquivo de texto.

Você pode instruir as ferramentas de processamento de texto a operar em bytes alterando o código do idioma . Especificamente, selecione a localidade “C”, que basicamente significa significa “nada sofisticado”. Na linha de comando, você pode escolher configurações de localidade com variáveis ​​de ambiente .

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

Isso não emitirá nenhum erro, mas também não será útil, pois target-fileainda é um arquivo binário que dificilmente conterá a maioria das sequências de pesquisa que você especificará.

Aliás, tr '\r' '\n'não é um comando muito útil, a menos que você tenha arquivos de texto restantes do Mac OS 9 ou anterior. \r(retorno de carro) era o separador de nova linha no Mac OS antes do Mac OS X. Desde o OSX, o separador de nova linha é \n(avanço de linha, o padrão unix) e os arquivos de texto não contêm retornos de carro. O Windows usa a seqüência de dois caracteres CR-LF para representar quebras de linha; tr -d '\r'converteria um arquivo de texto do Windows em um arquivo de texto Unix / Linux / OSX.

Então, como você pode pesquisar em um documento do Word na linha de comando? Um .docxdocumento do Word é na verdade um arquivo zip contendo vários arquivos, sendo os principais em XML .

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

O Mac OS X inclui o utilitário zipgrep para pesquisar dentro de arquivos zip.

zipgrep DeCSS Position-Paper-Final-Version.docx

O resultado não será muito legível, porque os arquivos XML no formato docx consistem principalmente em uma linha enorme. Se você deseja pesquisar dentro do texto do corpo principal do documento, extraia o arquivo word/document.xmldo arquivo morto. Observe que, além do texto do documento, este arquivo contém marcação XML que representa a estrutura do documento. Você pode massagear um pouco a marcação XML sedpara dividi-la em linhas gerenciáveis.

unzip -p Position-Paper-Final-Version.docx word/document.xml |
sed -e 's/></>\n</g' |
grep DeCSS
Gilles 'SO- parar de ser mau'
fonte
11
+1 para um bom resumo e bits extras. Eu tenho uma coisa a dizer, no entanto. Para formatar o xml, você pode usá- xml_pplo no pacote xml-twig-toolsDebian Gnu + Linux (não conhece um mac).
ctrl-alt-Delor
2
O Excel para Mac 2011 salva arquivos CSV com terminações de linha, de modo que essa chamada de tr é realmente relevante e útil.
Noah Yetter
11
Assim como o Outlook para Mac 2011, quando você exporta uma lista de contatos delimitados por tabulação.
Ivan X
11
Bem, eu não tenho reputação suficiente para rebaixar isso, mas essa resposta está totalmente incorreta. Começa com " tr[...] espera que suas entradas sejam arquivos de texto."; enquanto a especificação POSIX indica claramente "A entrada padrão pode ser qualquer tipo de arquivo". . Corrija sua resposta.
7heo.tk 26/09
@ 7heo.tk “esta resposta é absolutamente incorreto” é um exagero grosseiro, mas você está certo, tré suposto para processar a entrada binária (em particular, que é suposto processo nulo bytes corretamente). O POSIX não especifica claramente como deve lidar com entradas que não são uma sequência de caracteres. (Se eu fosse um implementador, passaria sequências de bytes inválidas por modificações (ou as removeria com -s) e levaria um defeito ao comitê padrão.) Evidentemente, o macOS reclama com elas.
Gilles 'SO- stop be evil'
13

Suponho que o seu mapa de caracteres das localidades seja UTF-8, para que você tenha problemas nos arquivos binários. Apenas mude para a localidade C:

LC_ALL=C tr '\r' '\n' < target-file | LC_ALL=C grep search-string
vinc17
fonte
você pode usar colchetes para evitar especificar o idioma duas vezes. LC_ALL=C ( tr '\r' '\n' < target-file | grep search-string ). No entanto, o docx não é C local. Is é utf16, compactado e complexo e é uma incógnita. Eu pareceria usar uma ferramenta que pode convertê-lo para um formato diferente que você possa processar, por exemplo, html ou odt (odt também é compactado, mas bem definido e fácil de interpretar).
CTRL-ALT-DELOR
11
A sintaxe com colchetes (parênteses) não funciona com todos os shells (nem bash, nem zsh, nem dash). Então, em relação ao arquivo do MS Word, isso depende. Eu tenho alguns desses arquivos em que o stringscomando fornece texto não criptografado.
21768
Como alternativa, ( export LC_ALL=C; tr '\r' '\n' < target-file | grep search-string; )deve funcionar.
precisa saber é
11
stringspossui super poderes: pode ler arquivos que não são apenas texto utf-8 ou ascii.
Ctrl-alt-delor
Desculpe pela ()coisa que pensei que funcionaria, graças a @ vinc17 por uma correção.
Ctrl-alt-delor