Ich brauche ein internationalisiertes Dienstprogramm, das dasselbe tut wie tr
:Ruft Zeichen aus Stream ab und ersetzt es durch ein entsprechendes Zeichen.
Es wird keine Sonderfalllösung wie Lower-to-Upper, sondern eine allgemeine Falllösung benötigt.
Ohne gorillion piped sed
ruft wenn möglich an.
Beachten Sie, dass tr
funktioniert nicht unter Linux:Es übersetzt Bytes, keine Zeichen. Dies schlägt bei Multibyte-Kodierungen fehl.
$ tr --version | head -n 1
tr (GNU coreutils) 8.23
$ echo $LC_CTYPE
en_US.UTF-8
$ echo 'Ångstrom' | tr Æ Œ
Ņngstrom
Akzeptierte Antwort:
GNU sed
funktioniert mit Multi-Byte-Zeichen. Also:
$ echo é½Æ | sed 'y/é½Æ/ABŒ/'
ABŒ
Es ist nicht so sehr, dass GNU tr
nicht internationalisiert wurde, aber keine Multi-Byte-Zeichen unterstützt (wie die Nicht-ASCII-Zeichen in UTF-8-Locales). GNU tr
würde mit Æ
funktionieren , Œ
solange sie Single-Byte wie im Zeichensatz iso8859-15 sind.
Mehr dazu unter Wie mache ich tr auf Nicht-ASCII-Zeichen (Unicode) aufmerksam?
Das hat jedenfalls nichts mit Linux zu tun, sondern mit dem tr
Implementierung auf dem System. Ob dieses System Linux als Kernel oder tr
verwendet für Linux erstellt wurde oder die Linux-Kernel-API verwendet, ist nicht relevant, da dieser Teil des tr
nicht relevant ist Funktionalität findet im Benutzerbereich statt.
Busybox tr
und GNU tr
sind am häufigsten in Distributionen von Software zu finden, die für Linux erstellt wurde, und unterstützen keine Multibyte-Zeichen, aber es gibt andere, die nach Linux portiert wurden, wie tr
der Heirloom-Toolchest (portiert von OpenSolaris) oder von ast-open, die dies tun.
Beachten Sie, dass sed
ist y
unterstützt keine Bereiche wie a-z
. Beachten Sie auch, dass, wenn das Skript, das sed 'y/é½Æ/ABŒ/'
enthält, perl
sein :
perl -Mopen=locale -Mutf8 -pe 'y/a-zé½Æ/A-ZABŒ/'
Oben wird erwartet, dass der Perl-Code in UTF-8 vorliegt, aber er wird die Eingabe in der Codierung des Gebietsschemas verarbeiten (und in derselben Codierung ausgeben). Wenn es in einem UTF-8-Gebietsschema aufgerufen wird, transliteriert es ein UTF-8 Æ
(0xc3 0x86) zu einem UTF-8 Œ
(0xc5 0x92) und in einem ISO8859-15 gleich, aber für 0xc6 -> 0xbc.
In den meisten Shells sollte es in Ordnung sein, diese UTF-8-Zeichen in einfachen Anführungszeichen zu haben, selbst wenn das Skript in einem Gebietsschema aufgerufen wird, in dem UTF-8 nicht der Zeichensatz ist (eine Ausnahme ist yash
was sich beschweren würde, wenn diese Bytes keine gültigen Zeichen im Gebietsschema bilden). Wenn Sie jedoch andere Anführungszeichen als einfache Anführungszeichen verwenden, kann dies zu Problemen führen. Zum Beispiel
perl -Mopen=locale -Mutf8 -pe "y/♣`/&'/"
würde in einem Gebietsschema fehlschlagen, in dem der Zeichensatz BIG5-HKSCS ist, da die Codierung von (0x5c) ist dort zufällig auch in einigen anderen Zeichen enthalten (wie
α
:0xa3 0x5c und die UTF-8-Kodierung von ♣
endet zufällig auf 0xa3).
Erwarten Sie auf keinen Fall Dinge wie
perl -Mopen=locale -Mutf8 -pe 'y/Á-Ź/A-Z/'
daran arbeiten, akute Akzente zu entfernen. Das Obige ist eigentlich nur
perl -Mopen=locale -Mutf8 -pe 'y/x{c1}-x{179}/x{41}-x{5a}/'
Das heißt, der Bereich basiert auf den Unicode-Codepoints. Daher sind Bereiche außerhalb sehr gut definierter Sequenzen, die zufällig „richtig sind, nicht nützlich ” Reihenfolge in Unicode wie A-Z
, 0-9
.
Wenn Sie akute Akzente entfernen möchten, müssen Sie fortgeschrittenere Tools verwenden wie:
perl -Mopen=locale -MUnicode::Normalize -pe '
$_ = NFKD($_); s/x{301}//g; $_ = NFKC($_)'
Das heißt, verwenden Sie Unicode-Normalisierungsformen, um Zeichen zu zerlegen, entfernen Sie die Akut-Akzente (hier die Kombinationsform U+0301
) und neu zusammensetzen.
Ein weiteres nützliches Werkzeug zum Transliterieren von Unicode ist uconv
von der Intensivstation. Obiges könnte zum Beispiel auch geschrieben werden als:
uconv -x '::NFKD; u0301>; ::NFKC;'
Würde aber nur mit UTF-8-Daten funktionieren. Sie benötigen:
iconv -t utf-8 | uconv -x '::NFKD; u0301>; ::NFKC;' | iconv -f utf-8
Um Daten im Gebietsschema des Benutzers verarbeiten zu können.