tr жалоб на «Неверная последовательность байтов»

Я новичок в UNIX, и я использую «Командную строку Mac OS X» Кирка МакЭлэрна, чтобы научить себя некоторым командам.

Я пытаюсь использовать tr и grep чтобы я мог искать текстовые строки в обычном Word Word MS-Office.

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

Но все это возвращается:

 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$ 

Я фактически запускаю ту же строку в скрипте, который я создал в vi и он выполняет поиск правильно.

grep – это инструмент обработки текста. Он ожидает, что их ввод будет текстовым . Кажется, что то же самое касается tr на macOS (хотя tr должен поддерживать двоичные файлы).

Компьютеры хранят данные как последовательности байтов . Текст представляет собой последовательность символов. Существует несколько способов кодирования символов в виде байтов, называемых символьными кодировками . Фактически стандартная кодировка символов в большинстве стран мира, особенно OSX, представляет собой UTF-8 , которая является кодировкой для набора символов Unicode . Есть только 256 возможных байтов, но более миллиона возможных символов Unicode, поэтому большинство символов кодируются как несколько байтов. UTF-8 является кодировкой переменной длины: в зависимости от символа для кодирования символа может принимать от одного до четырех байтов. Некоторые последовательности байтов не представляют никакого символа в UTF-8. Поэтому есть последовательности байтов, которые не являются допустимыми текстовыми файлами UTF-8.

tr жалуется, потому что столкнулся с такой последовательностью байтов. Он ожидает увидеть текстовый файл, закодированный в UTF-8, но он видит двоичные данные, которые недопустимы UTF-8.

Документ Microsoft Word не является текстовым файлом: это документ обработки текстов. Форматы документов обработки документов кодируют не только текст, но и форматирование, встроенные изображения и т. Д. Формат Word, как и большинство форматов обработки текстов, не является текстовым файлом.

Вы можете указать инструменты обработки текста для работы с байтами, изменив локаль . В частности, выберите локаль «C», что в основном означает «ничего необычного». В командной строке вы можете выбрать настройки локали с переменными среды .

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

Это не приведет к какой-либо ошибке, но ничего полезного не будет, поскольку target-file все еще является двоичным файлом, который вряд ли содержит большинство строк поиска, которые вы укажете.

Кстати, tr '\r' '\n' не очень полезная команда, если у вас нет текстовых файлов с Mac OS 9 или старше. \r (возврат каретки) был разделителем новой строки в Mac OS до Mac OS X. Поскольку OSX, разделитель новой строки – \n (строка строки, стандарт unix), а текстовые файлы не содержат возврат каретки. Windows использует двухсимвольную последовательность CR-LF для представления разрывов строк; tr -d '\r' преобразует текстовый файл Windows в текстовый файл Unix / Linux / OSX.

Итак, как вы можете искать в документе Word из командной строки? Документ Word .docx Word фактически представляет собой zip-архив, содержащий несколько файлов, основные из которых находятся в XML .

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

Mac OS X включает утилиту zipgrep для поиска внутри zip-файлов.

 zipgrep DeCSS Position-Paper-Final-Version.docx 

Результат не будет очень читабельным, потому что XML-файлы в формате docx в основном состоят из одной огромной линии. Если вы хотите выполнить поиск внутри основного текста документа, извлеките файл-файл word/document.xml из архива. Обратите внимание, что в дополнение к тексту документа этот файл содержит разметку XML, которая представляет структуру документа. Вы можете массировать разметку XML с помощью sed чтобы разделить его на управляемые строки.

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

Я полагаю, что ваш charmap из локалей UTF-8, так что у вас будут проблемы с двоичными файлами. Просто переключитесь на языковой стандарт C:

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