Поведение tr -c -d при удалении байтов со значениями, не являющимися символами

У меня возникли проблемы с пониманием этого абзаца из раздела «ОБОСНОВАНИЕ» на http://pubs.opengroup.org/onlinepubs/9699919799/utilities/tr.html.

Стандарт ISO POSIX-2:1993 имел параметр -c, который вел себя аналогично параметру -C, но не предоставлял функциональные возможности, эквивалентные параметру -c, указанному в POSIX.1-2008. Это означало, что историческая практика указания 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. Почему результат моего теста не соответствует тому, что написано в спецификации?


person Lone Learner    schedule 25.03.2015    source источник
comment
Разве это не говорит о том, что реализации, соответствующие версии спецификации 1993 года, будут нарушены, но более ранние реализации (исторические) и реализации, соответствующие спецификации 2008 года (и новее), будут работать? Или я что-то не так прочитал?   -  person Etan Reisner    schedule 25.03.2015


Ответы (1)


Поскольку вы используете CentOS, скорее всего, ваша команда tr из пакета GNU coreutils. GNU tr не делает (пока) различий между поведением -c и -C. В последних версиях tr и -c, и -C являются эквивалентными короткими опциями для опции --complement.

Согласно документации GNU для tr :

В настоящее время tr полностью поддерживает только однобайтовые символы. Со временем он будет поддерживать многобайтовые символы; когда это произойдет, опция -C приведет к тому, что он дополнит набор символов, тогда как -c заставит его дополнить набор значений. Это различие будет иметь значение только тогда, когда некоторые значения не являются символами, а это возможно только в локалях, использующих многобайтовые кодировки, когда входные данные содержат ошибки кодирования.

Я также обнаружил, что цитируемый абзац из спецификации POSIX сформулирован сбивчиво, но я согласен с интерпретацией Этана Рейснера, что «реализации, соответствующие версии спецификации 1993 года, будут нарушены, но более ранние реализации (исторические) и реализации, соответствующие версии 2008 ( и новее) будет работать».

В любом случае, GNU tr (пока) не реализует эту часть спецификации POSIX 2008 (т. е. различие между символами и значениями), поэтому его нельзя использовать для тестирование.

Кстати, у вас в команде tr -c -d "\000-\1777" есть лишнее 7.

person Anthony Geoghegan    schedule 25.06.2015