Zwischen Unicode-Normalisierungsformularen in der Unix-Befehlszeile konvertieren

22

In Unicode haben einige Zeichenkombinationen mehr als eine Darstellung.

Beispielsweise kann das Zeichen ä dargestellt werden als

  • "ä", das ist der Codepunkt U + 00E4 (zwei Bytes c3 a4bei UTF-8-Codierung) oder as
  • "ä", das sind die beiden Codepunkte U + 0061 U + 0308 (drei Bytes 61 cc 88in UTF-8).

Gemäß dem Unicode-Standard sind die beiden Darstellungen äquivalent, jedoch in unterschiedlichen "Normalisierungsformen", siehe UAX Nr. 15: Unicode-Normalisierungsformen .

Die Unix-Toolbox enthält alle Arten von Texttransformations-Tools, sed , tr , iconv und Perl. Wie kann ich eine schnelle und einfache NF-Konvertierung in der Befehlszeile durchführen?

glänzt
quelle
2
Es sieht so aus, als gäbe es ein "Unicode :: Normalization" -Modul für Perl, das dies tun sollte: search.cpan.org/~sadahiro/Unicode-Normalize-1.16/Normalize.pm
goldilocks
@ Goldilocks, wenn es eine CLI hatte ... Ich meine, ich mache perl -MUnicode::Normalization -e 'print NFC(...
ähm,

Antworten:

20

Sie können das uconvDienstprogramm von der Intensivstation aus verwenden . Die Normalisierung erfolgt durch Transliteration ( -x).

$ uconv -x any-nfd <<<ä | hd
00000000  61 cc 88 0a                                       |a...|
00000004
$ uconv -x any-nfc <<<ä | hd
00000000  c3 a4 0a                                          |...|
00000003

Auf Debian ist Ubuntu und andere Derivate uconvim libicu-devPaket. Auf Fedora, Red Hat und anderen Derivaten und in BSD-Ports ist es im icuPaket enthalten.

Gilles 'SO - hör auf böse zu sein'
quelle
Das funktioniert, danke. Sie müssen jedoch eine 30M-Entwicklungsbibliothek daneben installieren. Was noch schlimmer ist, ich konnte keine ordnungsgemäße Dokumentation für uconv selbst finden: Wo haben Sie gefunden any-nfd? Es sieht so aus, als ob die Entwicklung dieses Tools abgebrochen wurde, das letzte Update war 2005.
glts
2
@glts habe ich any-nfddurch Durchsuchen der Liste gefunden, die von angezeigt wird uconv -L.
Gilles 'SO- hör auf böse zu sein'
Auf Ubuntu mit sudo apt install icu-devtoolslaufen uconv -x any-nfc, aber nicht das einfachste Problem lösen , zB eine bugText.txt Datei mit "Iglésias, Bad-á, Good-á" konvertiert, indem uconv -x any-nfc bugText.txt > goodText.txtder gleiche Text beibehalten wird.
Peter Krauss
7

Python hat ein unicodedataModul in seiner Standardbibliothek, mit dem Unicode-Darstellungen durch folgende unicodedata.normalize()Funktionen übersetzt werden können:

import unicodedata

s1 = 'Spicy Jalape\u00f1o'
s2 = 'Spicy Jalapen\u0303o'

t1 = unicodedata.normalize('NFC', s1)
t2 = unicodedata.normalize('NFC', s2)
print(t1 == t2) 
print(ascii(t1)) 

t3 = unicodedata.normalize('NFD', s1)
t4 = unicodedata.normalize('NFD', s2)
print(t3 == t4)
print(ascii(t3))

Laufen mit Python 3.x:

$ python3 test.py
True
'Spicy Jalape\xf1o'
True
'Spicy Jalapen\u0303o'

Python ist nicht gut für Shell-One-Liner geeignet, kann jedoch ausgeführt werden, wenn Sie kein externes Skript erstellen möchten:

$ python3 -c $'import unicodedata\nprint(unicodedata.normalize("NFC", "ääääää"))'
ääääää

Für Python 2.x müssen Sie encoding line ( # -*- coding: utf-8 -*-) hinzufügen und Strings als Unicode mit dem Zeichen u markieren:

$ python -c $'# -*- coding: utf-8 -*-\nimport unicodedata\nprint(unicodedata.normalize("NFC", u"ääääää"))'
ääääää
Nykakin
quelle
3

Überprüfen Sie es mit dem Werkzeug hexdump:

echo  -e "ä\c" |hexdump -C 

00000000  61 cc 88                                          |a..|
00000003  

konvertiere mit iconv und überprüfe erneut mit hexdump:

echo -e "ä\c" | iconv -f UTF-8-MAC -t UTF-8 |hexdump -C

00000000  c3 a4                                             |..|
00000002

printf '\xc3\xa4'
ä
mtt2p
quelle
2
Dies funktioniert nur unter macOS. Es gibt unter Linux, FreeBSD usw. kein 'utf-8-mac'. Auch die Dekomposition mit dieser Kodierung folgt nicht der Spezifikation (sie folgt jedoch dem Normalisierungsalgorithmus des macOS-Dateisystems). Weitere Informationen: search.cpan.org/~tomita/Encode-UTF8Mac-0.04/lib/Encode/…
antonone
@antonone, um fair zu sein, obwohl in der Frage kein Betriebssystem angegeben wurde.
Roaima
1
@roaima Ja, deshalb habe ich angenommen, dass die Antwort auf allen Systemen funktionieren sollte, die auf Unix / Linux basieren. Die Antwort oben funktioniert nur unter macOS. Wenn man nach einer macOS-spezifischen Antwort sucht, funktioniert dies zum Teil. Ich wollte nur darauf hinweisen, weil ich neulich einige Zeit verloren habe und mich gefragt habe, warum ich utf-8-macunter Linux keine habe und ob dies normal ist.
Antonone
3

Der Vollständigkeit halber mit perl:

$ perl -CSA -MUnicode::Normalize=NFD -e 'print NFD($_) for @ARGV' $'\ue1' | uconv -x name
\N{LATIN SMALL LETTER A}\N{COMBINING ACUTE ACCENT}
$ perl -CSA -MUnicode::Normalize=NFC -e 'print NFC($_) for @ARGV' $'a\u301' | uconv -x name
\N{LATIN SMALL LETTER A WITH ACUTE}
Stéphane Chazelas
quelle
2

coreutils hat einen Patch, um einen richtigen zu bekommen unorm. funktioniert gut für mich auf 4byte wchars. folgen http://crashcourse.housegordon.org/coreutils-multibyte-support.html#unorm Das verbleibende Problem gibt es 2-Byte - wchar Systeme (Cygwin, Fenster, sowie AIX- und Solaris auf 32 - Bit), die Codepoints von oben zu transformieren müssen Ebenen in Ersatzpaare und umgekehrt, und die zugrunde liegende libunistring / gnulib kann das noch nicht verarbeiten.

Perl hat das unicharsTool, das auch die verschiedenen Normalisierungsformen in der Cmdline ausführt. http://search.cpan.org/dist/Unicode-Tussle/script/unichars

Rurban
quelle