删除具有非字符值的字节时tr -c -d的行为

Lon*_*ner 5 shell posix tr

我无法理解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
Run Code Online (Sandbox Code Playgroud)

该命令tr -c -d "\000-\1777"确实删除了带有值\x81和的字节\x82.为什么我的测试结果不符合规范中的内容?

Ant*_*ica 3

由于您使用的是 CentOS,因此您的命令很可能tr来自 GNUcoreutils软件包。GNUtr还没有区分 和 的-c行为-C。在 的最新版本中tr, 和-c都是-C该选项的等效短选项--complement

\n\n

根据tr 的 GNU 文档

\n\n
\n

目前 tr 仅完全支持单字节字符。最终它将支持多字节字符;当它这样做时,-C 选项将导致它补充字符集,而 -c 将导致它补充值集。仅当某些值不是字符时,这种区别才有意义,并且只有在输入包含编码错误时使用多字节编码的区域设置中才可能出现这种情况。

\n
\n\n

我还发现 POSIX 规范中引用的段落措辞混乱,但我\xe2\x80\x99d 同意 Etan Reisner\xe2\x80\x99s 的解释,即符合 1993 版本规范的 \xe2\x80\x9cimplementations 是损坏但较早的实现(历史)和符合 2008(及更新)规范的实现可以\xe2\x80\x9d 工作。

\n\n

无论如何,GNUtr还没有实现 2008 POSIX 规范的这一部分(即区分字符),因此它不能用于测试。

\n\n

顺便说一句,你的命令有多余7tr -c -d "\\000-\\1777"

\n