tr命令使用-c选项删除不是字符的字节时的行为

5
我不太理解http://pubs.opengroup.org/onlinepubs/9699919799/utilities/tr.html中'Rationale'部分的这段话。ISO POSIX-2:1993标准有一个-c选项,其行为类似于-C选项,但没有提供与POSIX.1-2008中指定的-c选项等效的功能。这意味着能够指定tr -cd\000-\177(将删除所有具有设置顶部位的字节)的历史实践将无效,因为在C语言环境中,值为八进制200至八进制377的字节不是字符。然而,我在CentOS 6.5系统上的测试似乎表明它确实有影响。
$ export LC_ALL=C
$ export LANG=C
$ locale
LANG=C
LC_CTYPE="C"
LC_NUMERIC="C"
LC_TIME="C"
LC_COLLATE="C"
LC_MONETARY="C"
LC_MESSAGES="C"
LC_PAPER="C"
LC_NAME="C"
LC_ADDRESS="C"
LC_TELEPHONE="C"
LC_MEASUREMENT="C"
LC_IDENTIFICATION="C"
LC_ALL=C
$ printf "\x41\x42\x81\x82" | od -t x1
0000000 41 42 81 82
0000004
$ printf "\x41\x42\x81\x82" | tr -c -d "\000-\1777" | od -t x1
0000000 41 42
0000002

命令tr -c -d "\000-\1777"删除了值为\x81\x82的字节。为什么我的测试结果与规范中的不一致?

这不是说符合1993年规范的实现将会出现问题,但早期的实现(历史)和符合2008年(及以后版本)规范的实现将能够正常工作吗?还是我理解错了什么? - Etan Reisner
1个回答

3

由于您正在使用CentOS,因此您的tr命令很可能来自GNU coreutils软件包。 GNU tr目前尚未区分-c-C的行为。在最近版本的tr中,-c-C都是--complement选项的等效短选项。

根据GNU tr文档

目前,tr仅完全支持单字节字符。最终,它将支持多字节字符;到那时,-C选项将使其补充字符集,而-c将使其补充值集。只有当某些值不是字符时,这种区别才会有影响,而且这仅在使用多字节编码的语言环境中输入包含编码错误时才可能发生。

我也认为 POSIX 规范中引用的段落措辞令人困惑,但我同意 Etan Reisner 的解释,“符合 1993 版本规范的实现将是错误的,但早期(历史)实现和符合 2008(及更新版本)规范的实现将能够工作”。
无论如何,GNU 的 tr 还没有实现 2008 POSIX 规范的这一部分(即区分字符),因此无法用于测试。
顺便说一下,在你的 tr -c -d "\000-\1777" 命令中有一个多余的 7

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接