Sto cercando di rimuovere alcuni caratteri dal file (UTF-8). Sto usando tr
a questo scopo:
tr -cs '[[:alpha:][:space:]]' ' ' <testdata.dat
Il file contiene alcuni caratteri stranieri (come "Латвийская" o "àé"). tr
sembra non capirli:li tratta come non alfa e li rimuove anche.
Ho provato a modificare alcune delle mie impostazioni internazionali:
LC_CTYPE=C LC_COLLATE=C tr -cs '[[:alpha:][:space:]]' ' ' <testdata.dat
LC_CTYPE=ru_RU.UTF-8 LC_COLLATE=C tr -cs '[[:alpha:][:space:]]' ' ' <testdata.dat
LC_CTYPE=ru_RU.UTF-8 LC_COLLATE=ru_RU.UTF-8 tr -cs '[[:alpha:][:space:]]' ' ' <testdata.dat
Sfortunatamente, nessuno di questi ha funzionato.
Come posso creare tr
capisci Unicode?
Risposta accettata:
Questa è una limitazione nota (1, 2, 3, 4, 5, 6) dell'implementazione GNU di tr
.
Non è tanto che non supporti stranieri , caratteri non inglesi o non ASCII, ma che non supporta i caratteri multibyte.
Quei caratteri cirillici verrebbero trattati correttamente, se scritti nel set di caratteri iso8859-5 (byte singolo per carattere) (e la tua locale stava usando quel set di caratteri), ma il tuo problema è che stai usando UTF-8 dove non ASCII i caratteri sono codificati in 2 o più byte.
GNU ha un piano (vedi anche) per risolvere il problema e il lavoro è in corso ma non ancora.
FreeBSD o Solaris tr
non avere il problema.
Nel frattempo, per la maggior parte dei casi d'uso di tr
, puoi usare GNU sed o GNU awk che supportano i caratteri multibyte.
Ad esempio, il tuo:
tr -cs '[[:alpha:][:space:]]' ' '
potrebbe essere scritto:
gsed -E 's/( |[^[:space:][:alpha:]])+/ /'
oppure:
gawk -v RS='( |[^[:space:][:alpha:]])+' '{printf "%s", sep $0; sep=" "}'
Per convertire tra lettere minuscole e maiuscole (tr '[:upper:]' '[:lower:]'
):
gsed 's/[[:upper:]]/l&/g'
(che l
è una L
minuscola , non il 1
cifra).
oppure:
gawk '{print tolower($0)}'
Per la portabilità, perl
è un'altra alternativa:
perl -Mopen=locale -pe 's/([^[:space:][:alpha:]]| )+/ /g'
perl -Mopen=locale -pe '$_=lc$_'
Se sai che i dati possono essere rappresentati in un set di caratteri a byte singolo, puoi elaborarli in quel set di caratteri:
(export LC_ALL=ru_RU.iso88595
iconv -f utf-8 |
tr -cs '[:alpha:][:space:]' ' ' |
iconv -t utf-8) < Russian-file.utf8