tr 抱怨“非法字节序列”

tr 抱怨“非法字节序列”

我是 UNIX 的新手,我正在使用 Kirk McElhearn 的“Mac OS X 命令行”来自学一些命令。

我正在尝试使用trgrep以便我可以在常规 MS-Office Word 文档中搜索文本字符串。

$ 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,并且它可以正确执行搜索。

答案1

grep是一个文本处理工具。它期望他们的输入是文本文件。 macOS 上似乎也是如此tr(尽管tr应该支持二进制文件)。

计算机将数据存储为序列字节。文本是字符序列。有几种将字符编码为字节的方法,称为字符编码。世界上大多数地方(尤其是 OSX 上)事实上的标准字符编码是UTF-8,这是一个编码统一码字符集。可能的字节只有 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 X 之前的 Mac OS 中的换行分隔符。从 OSX 开始,换行分隔符是\n(换行,unix 标准)并且文本文件不包含回车。 Windows 使用两个字符序列 CR-LF 来表示换行符;tr -d '\r'会将 Windows 文本文件转换为 Unix/Linux/OSX 文本文件。

那么如何从命令行在 Word 文档中进行搜索呢? Word文档.docx实际上是一个压缩档案包含几个文件,主要文件位于XML

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

Mac OS X 包括zipgrep用于搜索 zip 文件内部的实用程序。

zipgrep DeCSS Position-Paper-Final-Version.docx

结果的可读性不是很好,因为 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

答案2

我认为您的区域设置的字符映射是 UTF-8,因此您在二进制文件上会遇到问题。只需切换到 C 语言环境:

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

相关内容