Ich versuche, einige Zeichen aus der Datei (UTF-8) zu entfernen. Ich verwende tr
dazu:
tr -cs '[[:alpha:][:space:]]' ' ' <testdata.dat
Die Datei enthält einige fremde Zeichen (wie „Латвийская“ oder „àé“). tr
scheint sie nicht zu verstehen:Es behandelt sie als Nicht-Alpha und entfernt sie auch.
Ich habe versucht, einige meiner Gebietsschemaeinstellungen zu ändern:
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
Leider hat nichts davon funktioniert.
Wie kann ich tr
machen verstehst du Unicode?
Akzeptierte Antwort:
Das ist eine bekannte (1, 2, 3, 4, 5, 6) Einschränkung der GNU-Implementierung von tr
.
Es ist nicht so sehr, dass es Fremd nicht unterstützt , nicht-englische oder Nicht-ASCII-Zeichen, unterstützt aber keine Multibyte-Zeichen.
Diese kyrillischen Zeichen würden in Ordnung behandelt, wenn sie im Zeichensatz iso8859-5 (Einzelbyte pro Zeichen) geschrieben wären (und Ihr Gebietsschema diesen Zeichensatz verwendet hat), aber Ihr Problem ist, dass Sie UTF-8 verwenden, wo es kein ASCII ist Zeichen werden in 2 oder mehr Bytes kodiert.
GNU hat einen Plan (siehe auch), um das zu beheben, und die Arbeit ist im Gange, aber noch nicht so weit.
FreeBSD oder Solaris tr
habe das Problem nicht.
In der Zwischenzeit für die meisten Anwendungsfälle von tr
, können Sie GNU sed oder GNU awk verwenden, die Multibyte-Zeichen unterstützen.
Zum Beispiel Ihr:
tr -cs '[[:alpha:][:space:]]' ' '
könnte geschrieben werden:
gsed -E 's/( |[^[:space:][:alpha:]])+/ /'
oder:
gawk -v RS='( |[^[:space:][:alpha:]])+' '{printf "%s", sep $0; sep=" "}'
Um zwischen Klein- und Großbuchstaben umzuwandeln (tr '[:upper:]' '[:lower:]'
):
gsed 's/[[:upper:]]/l&/g'
(das l
ist ein kleiner L
, nicht die 1
Ziffer).
oder:
gawk '{print tolower($0)}'
Für die Portabilität perl
ist eine weitere Alternative:
perl -Mopen=locale -pe 's/([^[:space:][:alpha:]]| )+/ /g'
perl -Mopen=locale -pe '$_=lc$_'
Wenn Sie wissen, dass die Daten in einem Einzelbyte-Zeichensatz dargestellt werden können, können Sie sie in diesem Zeichensatz verarbeiten:
(export LC_ALL=ru_RU.iso88595
iconv -f utf-8 |
tr -cs '[:alpha:][:space:]' ' ' |
iconv -t utf-8) < Russian-file.utf8