tr скаржиться на "Незаконні послідовності байтів"


24

Я абсолютно новий для UNIX, і я використовую "Кінговий рядок Mac OS X" Кірка МакЛехрена, щоб навчити себе деяким командам.

Я намагаюся використовувати trі grepтак , що я можу шукати текстові рядки в регулярній MS-Office Word Document.

$ 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і він виконує пошук правильно.


Я не можу зрозуміти, чому tr поскаржиться, ви ввели те саме, що ви поставили у питанні? grep не знайде того, що ви хочете, xdoc - це неправильно визначений стандарт. Ніхто насправді не знає, що є в цих файлах, люди спроектували це реверсом, мабуть, стандарт не допоміг.
ctrl-alt-delor

Відповіді:


29

grepє інструментом обробки тексту. Він очікує, що їх введенням будуть текстові файли . Схоже, те саме стосується і trmacOS (навіть якщо trвін повинен підтримувати бінарні файли).

Комп'ютери зберігають дані як послідовності байтів . Текст - це послідовність символів. Існує кілька способів кодування символів у вигляді байтів, які називаються кодуваннями символів . Стандартним кодуванням символів у більшості країн світу, особливо в OSX, є UTF-8 , що є кодуванням для набору символів Unicode . Є лише 256 можливих байтів, але понад мільйон можливих символів Unicode, тому більшість символів закодовані як кілька байтів. UTF-8 - це кодування змінної довжини: в залежності від символу, для кодування символу може знадобитися від одного до чотирьох байтів. Деякі послідовності байтів не представляють жодного символу в UTF-8. Тому є послідовності байтів, які не є дійсними текстовими файлами UTF-8.

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

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

Ви можете доручити інструментам для обробки тексту працювати на байтах, змінивши локаль . Зокрема, виберіть локальний пункт "С", що в основному означає "нічого фантазійного". У командному рядку можна вибрати параметри локалі зі змінними середовища .

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 з командного рядка? Документ .docxWord - це фактично zip-архів, що містить декілька файлів, основні з яких є у XML .

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

Mac OS X включає в себе утиліту zipgrep для пошуку поштових файлів.

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

1
+1 за гарний підсумок та додаткові біти. Я маю сказати одне. Щоб відформатувати xml, ви можете використовувати xml_ppйого в пакеті xml-twig-toolsна Debian Gnu + Linux (не знаю mac).
ctrl-alt-delor

2
Excel для Mac 2011 зберігає файли CSV із закінченнями рядка, тому ця виклик tr є насправді досить актуальною та корисною.
Ной Ітер

1
Як і Outlook для Mac 2011, коли ви експортуєте список контактів з обмеженими вкладками.
Іван Х

1
Ну, у мене недостатньо репутації, щоб це спростувати, але ця відповідь є абсолютно невірною. Починається з " tr[...] очікують, що їх введенням будуть текстові файли."; в той час як специфікація POSIX чітко вказує "Стандартним входом може бути файл будь-якого типу." . Будь ласка, виправте свою відповідь.
7heo.tk

@ 7heo.tk «ця відповідь зовсім неправильно» є грубим перебільшенням можна , але ви маєте рацію, trце повинен обробляти двійковий вхід (зокрема, він повинен процес з нульовим байтом правильно). POSIX не чітко визначає, як слід мати справу з введенням, що не є послідовністю символів. (Якби я був реалізатором, я передавав би недійсні послідовності байтів через немодифіковані (або видаляв їх за допомогою -s) та виніс дефект зі стандартним комітетом.) Очевидно, tr на macOS скаржиться на них.
Жил "ТАК - перестань бути злим"

13

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

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

ви можете використовувати дужки, щоб уникнути вказівки мови двічі. LC_ALL=C ( tr '\r' '\n' < target-file | grep search-string ). Однак docx не є локальним. Це utf16 і на блискавці і складно, і хтось здогадається. Я би виглядав як використання інструменту, який може конвертувати його в інший формат, який ви можете обробити, наприклад, html або odt (odt також в блискавці, але добре визначений і простий для інтерпретації).
ctrl-alt-delor

1
Синтаксис із дужками (дужки) не працює з усіма оболонками (не bash, не zsh, не тире). Тоді, що стосується файлу MS Word, це залежить. У мене є кілька таких файлів, де stringsкоманда дає чіткий текст.
vinc17

Як варіант, ( export LC_ALL=C; tr '\r' '\n' < target-file | grep search-string; )слід працювати.
vinc17

1
stringsмає надпотужні повноваження: він може читати файли, які не є просто текстом utf-8 або ascii.
ctrl-alt-delor

Вибачте за ()те, що я думав, що це спрацює, завдяки @ vinc17 за виправлення.
ctrl-alt-delor
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.