Команда cut
имеет опцию -c
для работы с символами вместо байтов с опцией -b
. Но это, похоже, не работает, в en_US.UTF-8
локали:
Второй байт дает второй символ ASCII (который точно так же кодируется в UTF-8):
$ printf 'ABC' | cut -b 2
B
но не дает второго из трех греческих не-ASCII символов в локали UTF-8:
$ printf 'αβγ' | cut -b 2
�
Все в порядке - это второй байт .
Итак, вместо этого мы смотрим на второго персонажа :
$ printf 'αβγ' | cut -c 2
�
Это выглядит сломленным.
При некоторых экспериментах выясняется, что диапазон 3-4
показывает второй символ:
$ printf 'αβγ' | cut -c 3-4
β
Но это так же, как байты с 3 по 4:
$ printf 'αβγ' | cut -b 3-4
β
Так что -c
не больше, чем -b
для UTF-8.
Я ожидаю, что настройка языка не подходит для UTF-8, но, в сравнении, wc
работает как ожидалось;
Он часто используется для подсчета байтов с помощью option -c
( --bytes
).
(Обратите внимание на запутанные имена опций.)
$ printf 'αβγ' | wc -c
6
Но он также может считать символы с помощью option -m
( --chars
), который просто работает:
$ printf 'αβγ' | wc -m
3
Таким образом, моя конфигурация, кажется, в порядке - но что-то особенное cut
.
Может быть, он вообще не поддерживает UTF-8? Но кажется, что он поддерживает многобайтовые символы, иначе он не должен был бы поддерживать -b
и -c
.
Так что не так? И почему?
Насколько я могу судить, настройка локали выглядит правильно для utf8:
$ locale
LANG=en_US.UTF-8
LANGUAGE=en_US
LC_CTYPE=en_US.UTF-8
LC_NUMERIC="en_US.UTF-8"
LC_TIME="en_US.UTF-8"
LC_COLLATE="en_US.UTF-8"
LC_MONETARY="en_US.UTF-8"
LC_MESSAGES="en_US.UTF-8"
LC_PAPER="en_US.UTF-8"
LC_NAME="en_US.UTF-8"
LC_ADDRESS="en_US.UTF-8"
LC_TELEPHONE="en_US.UTF-8"
LC_MEASUREMENT="en_US.UTF-8"
LC_IDENTIFICATION="en_US.UTF-8"
LC_ALL=
Ввод, побайтно:
$ printf 'αβγ' | hd
00000000 ce b1 ce b2 ce b3 |......|
00000006
-c
использует тот же код, что и-b
. Вы смотрели на исходный код? Может быть, вы можете найти подсказку для чего-c
на самом деле.