У команді 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
працює як очікувалося;
Він часто використовується для підрахунку байтів, за допомогою параметра -c
( --bytes
).
(Зверніть увагу на заплутані назви опцій.)
$ printf 'αβγ' | wc -c
6
Але він також може рахувати символи з опцією -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
насправді призначено.