use*_*886 33 grep character-encoding text-processing binary tr
我是 UNIX 的新手,我正在使用 Kirk McElhearn 的“Mac OS X 命令行”自学一些命令。
我正在尝试使用tr
andgrep
以便我可以在常规 MS-Office Word 文档中搜索文本字符串。
$ tr '\r' '\n' < target-file | grep search-string
Run Code Online (Sandbox Code Playgroud)
但它返回的只是:
Illegal byte sequence.
Run Code Online (Sandbox Code Playgroud)
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$
Run Code Online (Sandbox Code Playgroud)
我实际上在我创建的脚本上运行了同一行,vi
并且它正确地进行了搜索。
Gil*_*il' 39
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
Run Code Online (Sandbox Code Playgroud)
这不会发出任何错误,但也不会做任何有用的事情,因为target-file
它仍然是一个二进制文件,不太可能包含您将指定的大多数搜索字符串。
顺便说一句,tr '\r' '\n'
除非您有 Mac OS 9 或更早版本遗留的文本文件,否则它不是一个非常有用的命令。\r
(回车)是 Mac OS X 之前的 Mac OS 中的换行符。从 OSX 开始,换行符是\n
(换行,unix 标准),文本文件不包含回车。Windows 使用两个字符的序列 CR-LF 来表示换行符;tr -d '\r'
会将 Windows 文本文件转换为 Unix/Linux/OSX 文本文件。
那么如何从命令行搜索 Word 文档呢?一个.docx
Word文件实际上是一个ZIP压缩文件包含多个文件,其中主要是在XML。
unzip -l Position-Paper-Final-Version.docx
Run Code Online (Sandbox Code Playgroud)
Mac OS X 包含用于在 zip 文件中搜索的zipgrep实用程序。
zipgrep DeCSS Position-Paper-Final-Version.docx
Run Code Online (Sandbox Code Playgroud)
结果不会很可读,因为 docx 格式的 XML 文件大多由一大行组成。如果要在文档的正文中搜索,请word/document.xml
从存档中提取文件。请注意,除了文档文本之外,该文件还包含表示文档结构的 XML 标记。您可以稍微调整 XML 标记sed
以将其拆分为可管理的行。
unzip -p Position-Paper-Final-Version.docx word/document.xml |
sed -e 's/></>\n</g' |
grep DeCSS
Run Code Online (Sandbox Code Playgroud)
vin*_*c17 18
我想你的语言环境的charmap是UTF-8,所以你会在二进制文件上遇到问题。只需切换到 C 语言环境:
LC_ALL=C tr '\r' '\n' < target-file | LC_ALL=C grep search-string
Run Code Online (Sandbox Code Playgroud)