tr mengeluh tentang “Urutan byte ilegal”

24

Saya baru untuk UNIX dan saya menggunakan Kirk McElhearn's "The Mac OS X Command Line" untuk mengajar diri saya beberapa perintah.

Saya mencoba untuk menggunakan trdan grepagar saya dapat mencari string teks dalam Dokumen Word MS-Office biasa.

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

Namun yang dikembalikan adalah:

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$ 

Saya sebenarnya menjalankan baris yang sama pada skrip yang saya buat vidan melakukan pencarian dengan benar.

pengguna74886
sumber
Saya tidak mengerti mengapa tr akan mengeluh, apakah Anda mengetik sama dengan yang Anda masukkan dalam pertanyaan? grep tidak akan menemukan apa yang Anda inginkan, xdoc adalah standar yang tidak ditentukan. Tidak ada yang benar-benar tahu apa yang ada di file-file itu, orang-orang telah merekayasa baliknya, tampaknya standarnya tidak membantu.
ctrl-alt-delor

Jawaban:

29

grepadalah alat pengolah teks. Itu mengharapkan input mereka menjadi file teks . Tampaknya hal yang sama berlaku untuk trmacOS (meskipun trseharusnya mendukung file biner).

Komputer menyimpan data sebagai urutan byte . Teks adalah urutan karakter. Ada beberapa cara untuk menyandikan karakter sebagai byte, yang disebut penyandian karakter . Pengkodean karakter standar de facto di sebagian besar dunia, terutama pada OSX, adalah UTF-8 , yang merupakan pengkodean untuk rangkaian karakter Unicode . Hanya ada 256 byte yang mungkin, tetapi lebih dari satu juta karakter Unicode yang mungkin, sehingga sebagian besar karakter dikodekan sebagai beberapa byte. UTF-8 adalah pengodean panjang variabel: tergantung pada karakter, dapat diperlukan satu hingga empat byte untuk menyandikan karakter. Beberapa urutan byte tidak mewakili karakter apa pun di UTF-8. Oleh karena itu, ada urutan byte yang bukan file teks UTF-8 yang valid.

trmengeluh karena mengalami urutan byte tersebut. Ia mengharapkan untuk melihat file teks yang dikodekan dalam UTF-8, tetapi ia melihat data biner yang tidak valid UTF-8.

Dokumen Microsoft Word bukan file teks: dokumen pengolah kata. Format dokumen pengolah kata tidak hanya mengkode teks, tetapi juga format, gambar yang disematkan, dll. Format Word, seperti kebanyakan format pengolah kata, bukan file teks.

Anda dapat menginstruksikan alat pengolah teks untuk beroperasi pada byte dengan mengubah lokal . Secara khusus, pilih "C" lokal, yang pada dasarnya berarti "tidak ada yang mewah". Pada baris perintah, Anda dapat memilih pengaturan lokal dengan variabel lingkungan .

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

Ini tidak akan memunculkan kesalahan apa pun, tetapi tidak akan melakukan apa pun yang berguna karena target-filemasih merupakan file biner yang tidak mungkin berisi sebagian besar string pencarian yang akan Anda tentukan.

Secara kebetulan, tr '\r' '\n'ini bukan perintah yang sangat berguna kecuali Anda memiliki file teks yang tersisa dari Mac OS 9 atau lebih lama. \r(carriage return) adalah pemisah baris baru di Mac OS sebelum Mac OS X. Sejak OSX, pemisah baris baru adalah \n(baris feed, standar unix) dan file teks tidak mengandung carriage return. Windows menggunakan urutan dua karakter CR-LF untuk mewakili jeda baris; tr -d '\r'akan mengkonversi file teks Windows menjadi file teks Unix / Linux / OSX.

Jadi bagaimana Anda bisa mencari dalam dokumen Word dari baris perintah? Sebuah .docxdokumen Word sebenarnya adalah arsip zip berisi beberapa file, yang utama berada di XML .

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

Mac OS X menyertakan utilitas zipgrep untuk mencari di dalam file zip.

zipgrep DeCSS Position-Paper-Final-Version.docx

Hasilnya tidak akan terlalu mudah dibaca karena file XML dalam format docx sebagian besar terdiri dari satu baris besar. Jika Anda ingin mencari di dalam teks badan utama dokumen, ekstrak file word/document.xmldari arsip. Perhatikan bahwa selain teks dokumen, file ini berisi markup XML yang mewakili struktur dokumen. Anda dapat memijat sedikit markup XML dengan seduntuk membaginya menjadi garis yang dikelola.

unzip -p Position-Paper-Final-Version.docx word/document.xml |
sed -e 's/></>\n</g' |
grep DeCSS
Gilles 'SANGAT berhenti menjadi jahat'
sumber
1
+1 untuk ringkasan yang baik dan bit ekstra. Saya punya satu hal untuk dikatakan. Untuk memformat xml, Anda dapat menggunakannya xml_ppdalam paket xml-twig-toolsdi Debian Gnu + Linux (tidak tahu mac).
ctrl-alt-delor
2
Excel untuk Mac 2011 menyimpan file CSV dengan ujung baris sehingga permintaan ini sebenarnya cukup relevan dan berguna.
Noah Yetter
1
Seperti halnya Outlook untuk Mac 2011 ketika Anda mengekspor daftar kontak yang dibatasi tab.
Ivan X
1
Yah, saya tidak punya reputasi yang cukup untuk meng-downvote ini, tetapi jawaban ini sama sekali tidak benar. Itu dimulai dengan " tr[...] mengharapkan input mereka menjadi file teks."; sedangkan spesifikasi POSIX dengan jelas menyatakan "Input standar dapat berupa jenis file apa pun." . Harap perbaiki jawaban Anda.
7heo.tk
@ 7heo.tk “jawaban ini sama sekali tidak benar” adalah exageration kotor, tapi Anda benar sedang, tryang seharusnya untuk memproses masukan biner (khususnya, itu seharusnya proses nol byte dengan benar). POSIX tidak secara jelas menentukan bagaimana seharusnya menangani input yang bukan urutan karakter. (Jika saya seorang pelaksana, saya akan melewati urutan byte yang tidak valid melalui tidak dimodifikasi (atau menghapusnya dengan -s), dan meningkatkan cacat dengan komite standar.) Jelas, tr macOS mengeluh tentang mereka.
Gilles 'SANGAT berhenti menjadi jahat'
13

Saya kira bahwa charmap Anda dari lokal adalah UTF-8, sehingga Anda akan memiliki masalah pada file biner. Alihkan saja ke C locale:

LC_ALL=C tr '\r' '\n' < target-file | LC_ALL=C grep search-string
vinc17
sumber
Anda dapat menggunakan tanda kurung untuk menghindari menentukan bahasa dua kali. LC_ALL=C ( tr '\r' '\n' < target-file | grep search-string ). Namun docx bukan C lokal. Apakah utf16 dan zip dan kompleks dan siapa pun menebak. Saya akan terlihat menggunakan alat yang dapat mengonversikannya ke format lain yang dapat Anda proses, misalnya html atau odt (odt juga di-zip, tetapi didefinisikan dengan baik dan mudah diinterpretasikan).
ctrl-alt-delor
1
Sintaks dengan tanda kurung (kurung) tidak berfungsi dengan semua shell (bukan bash, bukan zsh, bukan dash). Kemudian, mengenai file MS Word, itu tergantung. Saya memiliki beberapa file seperti itu di mana stringsperintahnya memberikan teks yang jelas.
vinc17
Atau, ( export LC_ALL=C; tr '\r' '\n' < target-file | grep search-string; )harus bekerja.
vinc17
1
stringsmemiliki kekuatan super: ia dapat membaca file yang bukan hanya utf-8 atau teks ascii.
ctrl-alt-delor
Maaf tentang ()hal yang saya pikir akan berhasil, terima kasih kepada @ vinc17 untuk perbaikannya.
ctrl-alt-delor