web-dev-qa-db-fra.com

tr se plaint de «séquence d'octets illégaux»

Je suis tout nouveau sous UNIX et j'utilise "La ligne de commande Mac OS X" de Kirk McElhearn pour m'enseigner quelques commandes.

J'essaie d'utiliser tr et grep pour pouvoir rechercher des chaînes de texte dans un document Word MS-Office standard.

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

Mais tout cela revient:

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$ 

J'ai en fait exécuté la même ligne sur un script que j'ai créé dans vi et il fait la recherche correctement.

26
user74886

grep est un outil de traitement de texte. Il s'attend à ce que leur entrée soit fichiers texte . Il semble qu'il en va de même pour tr sur macOS (même si tr est censé prendre en charge les fichiers binaires).

Les ordinateurs stockent les données sous forme de séquences de octets . Un texte est une séquence de caractères. Il existe plusieurs façons de coder les caractères sous forme d'octets, appelés codages de caractères . L'encodage de caractères standard de facto dans la plupart du monde, en particulier sous OSX, est TF-8 , qui est un encodage pour le jeu de caractères nicode . Il n'y a que 256 octets possibles, mais plus d'un million de caractères Unicode possibles, donc la plupart des caractères sont codés sur plusieurs octets. UTF-8 est un codage de longueur variable: selon le caractère, il peut prendre de un à quatre octets pour coder un caractère. Certaines séquences d'octets ne représentent aucun caractère en UTF-8. Par conséquent, il existe des séquences d'octets qui ne sont pas des fichiers texte UTF-8 valides.

tr se plaint car il a rencontré une telle séquence d'octets. Il s'attend à voir un fichier texte encodé en UTF-8, mais il voit des données binaires qui ne sont pas des UTF-8 valides.

Un document Microsoft Word n'est pas un fichier texte: c'est un document de traitement de texte. Les formats de document de traitement de texte codent non seulement le texte, mais également le formatage, les images incorporées, etc. Le format Word, comme la plupart des formats de traitement de texte, n'est pas un fichier texte.

Vous pouvez demander aux outils de traitement de texte de fonctionner sur les octets en modifiant locale . Plus précisément, sélectionnez les paramètres régionaux "C", ce qui signifie essentiellement "rien d'extraordinaire". Sur la ligne de commande, vous pouvez choisir les paramètres régionaux avec variables d'environnement .

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

Cela n'émettra aucune erreur, mais cela ne fera rien d'utile non plus puisque target-file est toujours un fichier binaire qui ne contient probablement pas la plupart des chaînes de recherche que vous spécifierez.

Par ailleurs, tr '\r' '\n' n'est pas une commande très utile à moins qu'il ne reste des fichiers texte de Mac OS 9 ou d'une version antérieure. \r (retour chariot) était le séparateur de nouvelle ligne dans Mac OS avant Mac OS X. Depuis OSX, le séparateur de nouvelle ligne est \n (saut de ligne, norme Unix) et les fichiers texte ne contiennent pas de retour chariot. Windows utilise la séquence de deux caractères CR-LF pour représenter les sauts de ligne; tr -d '\r' convertirait un fichier texte Windows en un fichier texte Unix/Linux/OSX.

Alors, comment pouvez-vous rechercher dans un document Word à partir de la ligne de commande? UNE .docx Le document Word est en fait un archive Zip contenant plusieurs fichiers, les principaux étant en XML .

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

Mac OS X inclut l'utilitaire zipgrep pour rechercher dans les fichiers Zip.

zipgrep DeCSS Position-Paper-Final-Version.docx

Le résultat ne sera pas très lisible car les fichiers XML au format docx se composent principalement d'une énorme ligne. Si vous souhaitez effectuer une recherche dans le corps du texte du document, extrayez le fichier Word/document.xml de l'archive. Notez qu'en plus du texte du document, ce fichier contient un balisage XML qui représente la structure du document. Vous pouvez masser un peu le balisage XML avec sed pour le diviser en lignes gérables.

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

Je suppose que votre charmap des locales est UTF-8, donc vous aurez des problèmes avec les fichiers binaires. Passez simplement aux paramètres régionaux C:

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