Це відоме ( 1 , 2 , 3 , 4 , 5 , 6 ) обмеження реалізації GNU tr
.
Справа не стільки в тому, що він не підтримує іноземні , не англійські або не ASCII символи, але і не підтримує багатобайтові символи.
Ці кириличні символи вважатимуться нормально, якщо вони написані в наборі символів iso8859-5 (однобайтовий на кожний символ) (і ваша локаль використовувала цю схему), але ваша проблема полягає в тому, що ви використовуєте UTF-8 там, де не ASCII символи кодуються в 2 або більше байтів.
GNU має план (див. Також ), щоб виправити це, і робота ведеться, але ще не існує.
У FreeBSD або Solaris tr
проблем немає.
Тим часом, для більшості випадків використання tr
ви можете використовувати GNU sed або GNU awk, які підтримують багатобайтові символи.
Наприклад, ваші:
tr -cs '[[:alpha:][:space:]]' ' '
можна було написати:
gsed -E 's/( |[^[:space:][:alpha:]])+/ /'
або:
gawk -v RS='( |[^[:space:][:alpha:]])+' '{printf "%s", sep $0; sep=" "}'
Для перетворення між малим і великим регістром ( tr '[:upper:]' '[:lower:]'
):
gsed 's/[[:upper:]]/\l&/g'
(тобто l
малі L
, а не 1
цифри).
або:
gawk '{print tolower($0)}'
Щодо мобільності - perl
це ще одна альтернатива:
perl -Mopen=locale -pe 's/([^[:space:][:alpha:]]| )+/ /g'
perl -Mopen=locale -pe '$_=lc$_'
Якщо ви знаєте, що дані можуть бути представлені в однобайтовому наборі символів, ви можете обробити їх у цій діаграмі:
(export LC_ALL=ru_RU.iso88595
iconv -f utf-8 |
tr -cs '[:alpha:][:space:]' ' ' |
iconv -t utf-8) < Russian-file.utf8