tr reclama de "sequência de bytes ilegal"

22

Sou novo no UNIX e estou usando "A linha de comando do Mac OS X", de Kirk McElhearn, para me ensinar alguns comandos.

Eu estou tentando usar tr e grep para que eu possa procurar por cadeias de texto em um documento do Word MS-Office regular.

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

Mas tudo que ele 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 corri a mesma linha em um script que criei em vi e ele faz a pesquisa corretamente.

    
por user74886 09.07.2014 / 00:14

2 respostas

26

grep é uma ferramenta de processamento de texto. Ele espera que a entrada deles seja arquivos de texto . Parece que o mesmo vale para tr no macOS (mesmo que tr deva 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 é um 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, então a maioria dos caracteres são codificados como múltiplos bytes. O UTF-8 é uma codificação de tamanho variável: dependendo do caractere, ele 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, há seqüências de bytes que não são arquivos de texto UTF-8 válidos.

tr está reclamando porque encontrou essa sequência de bytes. Ele espera ver um arquivo de texto codificado em UTF-8, mas ele 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. 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 ferramentas de processamento de texto para operar em bytes, alterando o local . Especificamente, selecione a localidade "C", que basicamente significa "nada extravagante". Na linha de comando, você pode escolher configurações de local com variáveis de ambiente .

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

Isso não emitirá nenhum erro, mas não fará nada útil, pois target-file ainda é um arquivo binário que provavelmente não contém a maioria das sequências de pesquisa que você especificar.

A propósito, 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. Como o OSX, o separador de nova linha é \n (alimentação de linha, o padrão unix) e arquivos de texto não contêm retornos de carro. O Windows usa a seqüência de dois caracteres CR-LF para representar as 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 a partir da linha de comando? Um documento .docx 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ê quiser procurar dentro do texto do corpo principal do documento, extraia o arquivo word/document.xml do arquivo. Observe que, além do texto do documento, esse arquivo contém uma marcação XML que representa a estrutura do documento. Você pode massagear um pouco a marcação XML com sed dividir em linhas gerenciáveis.

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

Suponho que o seu charmap das localidades seja UTF-8, para que você tenha problemas com arquivos binários. Basta mudar para o idioma C:

LC_ALL=C tr '\r' '\n' < target-file | LC_ALL=C grep search-string
    
por 09.07.2014 / 00:34