Команда 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
на самом деле.Ответы:
Вы не сказали, что
cut
вы используете, но так как вы упомянули опцию GNU long,--characters
я предполагаю, что это тот вариант . В этом случае обратите внимание на этот отрывок изinfo coreutils 'cut invocation'
:(выделение добавлено)
На данный момент GNU
cut
всегда работает в терминах однобайтовых «символов», поэтому ожидаемое поведение ожидается.Поддерживая оба
-b
и-c
опции требуют POSIX - они не были добавлены в GNU ,cut
потому что он имел поддержку многобайтной и они работали должным образом, но , чтобы не дать ошибки на POSIX-совместимых вход. То же самое-c
было сделано в некоторых другихcut
реализациях, хотя не во FreeBSD и OS X , по крайней мере.Это историческое поведение в
-c
.-b
был добавлен, чтобы взять на себя роль байта, чтобы он-c
мог работать с многобайтовыми символами. Может быть, через несколько лет он будет работать, как хотелось бы последовательно, хотя прогресс не был быстрым (прошло уже более десяти лет). GNUcut
еще даже не реализует эту-n
опцию , даже если она ортогональна и предназначена для облегчения перехода. Существуют потенциальные проблемы совместимости со старыми сценариями, которые могут быть проблемой, хотя я не знаю точно, в чем причина.источник
tr
документации GNU . и дажеtar
если я не помню. Я думаю, это большой проект.cut
? Например, где можно скачать исходники для пропатченыхcut
? Или было бы проще использовать другую утилиту? (grep
решение ниже не работает гладко с диапазонами, например5-8,44-49
)cut -c
здесь: superuser.com/questions/506164/…colrm
(частьutil-linux
, должна быть уже установлена в большинстве дистрибутивов), кажется, справляется с интернационализацией гораздо лучше:Остерегайтесь нумерации:
colrm N
удаляете столбцы изN
, печатая символы доN-1
.( кредиты )
источник
Так как многие
grep
реализации поддерживают многобайтовые вычисления, вы также можете использовать ихgrep -o
для имитации некоторых примененийcut -c
.Отрегулируйте количество периодов для имитации
cut
диапазонов.источник