Когда я бегу echo é | tr é e
, я получаю ee
, а не e
, которого я ожидал.
Вот результат команды locale
:
LANG=en_US.UTF-8
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=
Покажите результат выполнения команды locale
.
@glennjackman: У меня такая же проблема, хотя все мои locale
записи "C.UTF-8"
.
Похоже, tr
плохо справляется с широкими символами.
$ echo 'é' | od -c
0000000 � � \n
0000003
$ echo 'é' | tr 'é' e | od -c
0000000 e e \n
0000003
Поскольку левый набор символов имеет длину 2 байта персонажи, tr
повторяет последний символ правого набора до тех пор, пока он не станет такой же длины.
$ echo 123456789 | tr 2468 xy
1x3y5y7y9
Вы можете предпочесть sed
для обработки символов, отличных от ASCII.
$ echo 'é' | sed 's/é/e/g' | od -c
0000000 e \n
0000002
$ echo 'é' | sed 'y/é/e/' | od -c
0000000 e \n
0000002
Спасибо за ваш вклад. Я думаю, вы правы. С практической точки зрения sed
будет правильным решением. Чтобы было ясно, вы говорите, что 'é' , также известный как '\130', на самом деле имеет ширину в два символа? (может быть, 2 байта в ширину?) И в результате tr
успешно транслитерирует два символа, полученные в качестве входных данных, как и было запрошено. Единственная ошибка здесь — это мое понимание команды tr
или ее ввода. Верно?
Да, наверное, моя формулировка недостаточно точна. Вероятно, это проблема байтов и символов: tr кажется байт-ориентированным, sed - символьным.
'é' состоит из двух символов и будет производить 'ee' при использовании tr
.
$ echo 'é' | tr 'é' 'e'
ee
Транслитерируйте 'é' в два символа, литерал 'e', за которым следует '\b', символ возврата, чтобы удалить второй 'e'.
$ echo 'é' | od -c
0000000 � � \n
0000003
$ echo é | tr 'é' 'e\b' |od -c
0000000 e \b \n
0000003
Обновлено: этот подход ошибочен. $ echo é | tr 'é' 'e\b'
похоже, что это работает, но может привести к странным результатам. Хотя вы видите букву «e» на своем терминале, на самом деле ваш терминал отображает «e\b». Это буква «е», за которой следует непечатаемый символ возврата. Лучше использовать sed
. sed 'y|é|e|'
Хороший вопрос. Это также происходит с другими буквами ударения, но не с другими символами, такими как
^
или$
.