Unicode-Normalisierer

Unicode hat vier Normalisierungsformen, und sie sind nicht austauschbar. NFC und NFD ordnen dasselbe Zeichen zwischen einem Codepunkt und einer Basis mit kombinierendem Zeichen um; NFKC und NFKD gehen weiter und schreiben Zeichen um, die einander nur ähneln — die Ligatur fi, das Vollbreiten-A, die eingekreiste ①, die römische Ziffer Ⅻ. Diese Seite schickt denselben Text durch alle vier, gibt eine Zeile je Zeichen aus, die sagt, was sich wie und warum verändert hat, zählt Grapheme gegen Codepunkte und UTF-8-Bytes und vergleicht zwei Zeichenfolgen unter der Form Ihrer Wahl. Die zweite Hälfte betrifft die Zeichen, die gar nicht erst auftauchen: Nullbreiten-Leerzeichen, Verbinder, bidirektionale Steuerzeichen, Variationsselektoren, C0- und C1-Steuerzeichen, Codepunkte für private Nutzung und kaputte Ersatzhälften, jeweils mit Position und Namen, und mit der Option, sie aus einer Kopie des Textes zu entfernen.
Die gesamte Verarbeitung erfolgt lokal in Ihrem Browser — Ihre Daten werden niemals auf einen Server hochgeladen.

Sie wissen nicht, was Normalisierung ist? Unicode-Normalisierung auf Deutsch erklärt — warum é ein oder zwei Zeichen sein kann und warum das eine Anmeldung kaputt macht.
Form zur Anzeige und zum Vergleich:
Die beiden Felder vergleichen nach:
NFC (noch nichts)
NFD (noch nichts)
NFKC (noch nichts)
NFKD (noch nichts)
Noch nichts verglichen. Fügen Sie die beiden Zeichenfolgen ein und drücken Sie Die beiden Zeichenfolgen vergleichen.
erste Zeichenfolge, normalisiert (noch nichts)
zweite Zeichenfolge, normalisiert (noch nichts)
Noch nichts geprüft. Drücken Sie Auf unsichtbare und gefährliche Zeichen prüfen und dann Entfernen, wenn Sie den Text ohne diese Zeichen möchten.
Text ohne die ausgewählten Klassen (noch nichts)
Strg+Eingabe im ersten Feld führt den aktiven Modus aus.
Wählen Sie einen Modus und klicken Sie auf seine Aktionsschaltfläche. Normalisieren schreibt alle vier Formen Ihres Textes und eine Zeile je Zeichen; Vergleichen sagt, ob zwei Zeichenfolgen nach der Normalisierung gleich sind; Prüfen listet die Zeichen auf, die nicht sichtbar sind, und kann sie entfernen. Die Schaltfläche Selbsttest führt jeden dokumentierten Fall in der Datendatei dieser Seite erneut aus, jedes Zeichen aus den Tabellen für unsichtbare und Steuerzeichen und meldet die Anzahl hier.
Jedes Zeichen, eine Zeile je Zeichen:was das Zeichen ist, was die vier Formen damit tun und warum. Eine schattierte Zeile ist ein Zeichen, das mindestens eine Form verändert; die Spalte NFD zeigt, in was das Zeichen zerfällt, wenn es überhaupt zerfällt.
Wie viele Zeichen sind das?Derselbe Text, viermal gezählt: Grapheme-Cluster (was ein Leser zählt), Codepunkte (was Unicode vergibt), UTF-16-Einheiten (was JavaScript indiziert) und UTF-8-Bytes (was übertragen wird). Die Normalisierung verschiebt die Zahlen zwischen der zweiten und dritten Spalte, ohne die erste zu verändern.
Was gefunden wurde, in der Reihenfolge des Auftretens:die Position zählt Codepunkte, die Klasse ist die, zu der das Zeichen gehört, und die Anmerkung sagt, was dieses Zeichen mit allem macht, was den Text als Nächstes liest.
Die Klassen, die diese Seite als verdächtig behandelt:die Tabelle wird aus dem Scanner selbst gedruckt, sodass die Wörter auf dieser Seite und das Verhalten der Schaltflächen nicht auseinanderlaufen können. Der Schweregrad bezieht sich auf die Wirkung auf einen Vergleich, nicht darauf, wie wahrscheinlich das Zeichen harmlos ist.
Zeichen für private Nutzung werden aus einem anderen Grund als verdächtig gelistet als die übrigen: Sie werden zwar gezeichnet, haben aber keine vereinbarte Bedeutung, daher ist derselbe Codepunkt in jeder Schrift, die ihn definiert, ein anderes Bild.
Wie groß eine Eingabe diese Seite annimmt und warum:Normalisierung baut die gesamte Zeichenfolge neu auf, und diese Seite führt mehrere davon sowie einen Scan und eine Graphemzählung aus, daher wächst der Aufwand geradlinig mit der Länge der Eingabe. Die Grenzen unten bestehen, weil die Tabelle je Zeichen im Dokument gezeichnet wird, und eine Tabelle mit einer Million Zeilen ist genau das, was einen Browser tatsächlich stoppt.
Was ist Unicode-Normalisierung?

Unicode bietet für manche Zeichen mehr als eine Schreibweise. Der Buchstabe é kann ein einzelner Codepunkt sein, U+00E9, oder ein gewöhnliches e, gefolgt von einem kombinierenden Akut, U+0065 U+0301. Beide sehen auf dem Bildschirm gleich aus, drucken gleich, und als Zeichenfolgen sind sie verschieden: Sie haben unterschiedliche Längen, unterschiedliche UTF-8-Bytes, und 'é' === 'e\u0301' ist false.

Das ist keine Kuriosität, sondern eine Fehlerklasse. Ob Sie die eine oder die andere Form bekommen, hängt vom Tastaturlayout, dem Betriebssystem, der Eingabemethode und davon ab, ob der Text je über eine Textverarbeitung kopiert wurde. Eine Passwortprüfung, ein eindeutiger Datenbankindex, eine Sperrliste oder ein Cache-Schlüssel, der Zeichenfolgen byteweise vergleicht, behandelt die beiden Schreibweisen als zwei verschiedene Werte — so kann ein Nutzer ein Passwort auf einem Gerät setzen und sich auf einem anderen nicht anmelden, und dasselbe Wort kann in einer Liste bereits vergebener Namen zweimal erscheinen.

Die Version in 30 Sekunden: NFC und NFD sind derselbe Text, nur auf zwei Arten geschrieben — NFC fasst zusammen (e + Akzent wird zu einem Zeichen), NFD zerlegt (ein Zeichen wird zu e + Akzent). Sie sollen verlustfrei sein und sind die beiden Formen für Vergleich und Speicherung. NFKC und NFKD tun alles, was die ersten beiden tun, ersetzen darüber hinaus auch Kompatibilitätszeichen: die Ligatur fi wird zu zwei Buchstaben, ½ wird zu 1⁄2, die römische Ziffer ⅲ wird zu XII, ein Vollbreiten-A wird zu einem gewöhnlichen A. Genau das wünscht sich ein Suchindex oder ein Stichwortfilter, und genau das darf man niemals auf ein Passwort anwenden.
Warum vier Formen und nicht eine

Die Trennung besteht, weil zwei verschiedene Ziele bedient werden. Zusammensetzen und Zerlegen von Text ist eine kanonische Änderung: Das Ergebnis bedeutet dasselbe, und bei den ersten beiden Formen geht nichts verloren. Das Auflösen von Ligaturen, Hochstellungen, eingekreisten Buchstaben und Vollbreitenformen ist dagegen eine Kompatibilitäts-Änderung: Sie erfolgt zur Erleichterung des Abgleichs, und sie zerstört tatsächlich die Unterscheidung zwischen zwei Zeichenfolgen, die Unicode als verschieden ausweist. Die vier Formen sind alle Kombinationen der beiden Entscheidungen.

Die Tabelle oben ist die Fallliste der Datendatei dieser Seite, geprüft gegen die eigene String.prototype.normalize der Plattform, und der Selbsttest prüft jede Zeile davon vor Ihren Augen erneut. Lesen Sie die ersten beiden Zeilen zusammen: Es ist derselbe Text, zweimal geschrieben, und nach der Normalisierung sind es dieselbe Zeichenfolge.

Durchgerechnete Beispiele

Das sind die Zeichenfolgen, die die Schaltfläche Beispiel durchgeht; die Seite normalisiert sie live, statt sie als vorgegebene Antworten einzutippen. Jede wurde gewählt, weil eine Form etwas Sichtbares mit ihr macht.

Kompatibilitätszeichen: was NFKC kostet

NFKC und NFKD sind verlustbehaftet, und der Verlust ist beabsichtigt. Sie beantworten die Frage „ist das dasselbe Wort“, nicht die Frage „ist das dieselbe Zeichenfolge“. Daraus folgen drei Konsequenzen, die im Produktivcode leicht falsch gehandhabt werden:

  • Speichern Sie niemals ein Passwort, ein Token oder eine Signatur in einer Kompatibilitätsform. Zwei verschiedene Eingaben würden auf denselben gespeicherten Wert zusammenfallen, wodurch eine Längen- oder Zeichenprüfung schwächer wird. Normalisieren Sie Passwörter mit NFC (oder gar nicht) und vergleichen Sie sie byteweise, nachdem auf beiden Seiten genau dasselbe geschehen ist.
  • Eine Kompatibilitätsfaltung kann ein Zeichen in mehrere verwandeln. Die Ligatur fi ist ein Codepunkt, der zu zwei Buchstaben wird, daher kann ein Feld, das vor der Normalisierung auf Länge geprüft wurde, danach länger sein. Erst normalisieren, dann validieren, dann speichern.
  • NFKC entfernt nicht alles Unsichtbare. Ein Variationsselektor übersteht NFKC und NFKD, ebenso ein Nullbreiten-Verbinder. Deshalb hat diese Seite einen Prüfmodus: Normalisierung beantwortet eine Frage zur Form und Identität eines Zeichens, der Scanner beantwortet die Frage, ob überhaupt etwas da ist.
Grapheme, Codepunkte und Bytes

Die Normalisierung verändert die zweite dieser Zahlen und lässt die erste meist in Ruhe. Die drei Zahlen sind alle „die Länge des Textes“ und alle verschieden, weshalb ein Formularfeld mit einer Begrenzung auf 20 Zeichen zu einer Zeichenfolge gehören kann, die 20 Codepunkte, 30 UTF-16-Einheiten und 47 Bytes lang ist.

Die Zahl in der Graphemspalte ist das, was ein Mensch zählt. Die Lücke zwischen ihr und der Codepunktanzahl ist genau der Gegenstand des Scanners: Ein Name aus 12 Codepunkten kann als 12 Buchstaben erscheinen, als 3 Buchstaben mit 9 unsichtbaren Zeichen dazwischen oder als ein einziges Emoji.

Die Zeichen, die Sie nicht sehen können

Ein Nullbreiten-Leerzeichen belegt keine Breite, verändert kein Schriftbild und ist ein echtes Zeichen mit einem echten Codepunkt. Zwei Bezeichner, die auf dem Bildschirm identisch aussehen, können sich durch eines davon unterscheiden — so kann ein Name in einer Liste ein Hochstapler sein, der anders sortiert, sucht und authentifiziert als der Name daneben. Dasselbe gilt für die bidirektionalen Steuerzeichen, die eine Zeichenfolge in einer anderen Reihenfolge darstellen können, als sie geschrieben wurde — ein Trick, mit dem Dateinamen getarnt wurden.

Der Scanner im dritten Modus listet jedes dieser Zeichen mit seiner Position auf: Nullbreiten- und Verbindungszeichen, bidirektionale Steuerzeichen, Variationsselektoren, ungewöhnliche Leerzeichen, C0- und C1-Steuerzeichen, Codepunkte für private Nutzung und einen Ersatz, der keine Hälfte eines gültigen Paares ist und daher gar kein Zeichen ist. Die Klassentabelle weiter oben auf dieser Seite beschreibt, was jede Klasse bewirkt, und die Schaltfläche zum Entfernen löscht eine Kopie dieser Zeichen, ohne Ihre Eingabe zu berühren.

Die Fehler, die diese Seite aufdecken soll
  • Zwei Zeichenfolgen vergleichen, ohne sie zu normalisieren. 'é' === 'e\u0301' ist falsch. Normalisieren Sie beide Seiten mit derselben Form, bevor Sie vergleichen, und verwenden Sie dieselbe Form im Index, gegen den Sie vergleichen.
  • Nur auf einer Seite normalisieren. Eine Suche, die die Anfrage normalisiert, den gespeicherten Wert aber nicht, findet nichts und sieht wie ein Datenproblem aus, nicht wie ein Normalisierungsproblem.
  • Ein Formular mit einer Kompatibilitätsform gestalten und es als NFC-sicher bezeichnen. NFKC auf ein Passwort angewendet verkürzt den Raum möglicher Passwörter und führt Eingaben zusammen, die verschieden sein sollten.
  • Die Annahme, eine Normalisierungsform behebe eine Fälschung. Sie entfernt weder einen Nullbreiten-Verbinder noch einen Variationsselektor oder ein Homoglyph — ein kyrillisches а und ein lateinisches a sind verschiedene Codepunkte, die NFC unberührt lässt.
  • Einer Zeichenanzahl vertrauen. Die Anzahl, die ein Nutzer sieht, die Anzahl, die eine Datenbankspalte erzwingt, und die Anzahl, die ein Byte-Limit erzwingt, sind drei verschiedene Zahlen, und die Zeilen oben zeigen, wie weit sie auseinanderliegen können.
  • Die Annahme, dass Sie NFC erhalten. Text, der aus einer Eingabemethode, einer Datei oder einem anderen System kommt, liegt in der Form vor, die dieses System erzeugt hat. Diese Seite startet mit NFC, weil das die Form ist, die für das Web vorgesehen ist — nicht weil das Ihre Eingabe ist.
Kurze Antworten

„Warum sind diese beiden Zeichenfolgen nicht gleich, obwohl sie gleich aussehen?“

Weil eines davon mit einem zusammengesetzten Zeichen geschrieben ist und das andere mit einem Basisbuchstaben plus kombinierendem Zeichen oder weil eines davon ein Zeichen enthält, das gar nichts zeichnet. Wechseln Sie in den Vergleichsmodus und geben Sie je eine Zeichenfolge in jedes Feld: Die Seite meldet die erste Position, an der sich die normalisierten Zeichenfolgen unterscheiden, und was an dieser Position in jeder von ihnen steht.

„Welche Form sollte ich in einer Anwendung verwenden?“

NFC für alles, was ein Mensch liest, anzeigt, speichert und durchsucht — die Form, die das W3C für das Web empfiehlt. NFD ist die richtige Antwort, wenn der Code dahinter Basisbuchstaben und getrennte Zeichen erwartet, was in der Textverarbeitung und auf manchen Dateisystemen unter macOS üblich ist. Verwenden Sie NFKC oder NFKD nur dort, wo Sie abgleichen statt speichern: Suchindizes, Stichwortfilter, Dublettenerkennung.

„Ist eine bereits normalisierte Zeichenfolge noch normalisiert, nachdem ich etwas angehängt habe?“

Nicht unbedingt. Normalisierung bleibt beim Aneinanderhängen nicht erhalten: Das Verbinden zweier NFC-Zeichenfolgen kann eine Folge erzeugen, die NFC anders geschrieben hätte, weil ein kombinierendes Zeichen am Anfang der zweiten Zeichenfolge sich an das Zeichen am Ende der ersten anhängen kann. Normalisieren Sie nach dem Zusammensetzen, nicht nur davor.

„Entfernt die Normalisierung die unsichtbaren Zeichen?“

Nein, mit einer teilweisen Ausnahme: NFKC und NFKD ersetzen das geschützte Leerzeichen durch ein gewöhnliches Leerzeichen, was ein sichtbares Ergebnis einer Kompatibilitätsfaltung ist. Alles andere — Nullbreiten-Leerzeichen, Verbinder, bidirektionale Steuerzeichen, Variationsselektoren — bleibt in allen vier Formen unberührt. Dafür gibt es den dritten Modus.

„Warum ändert sich die Byteanzahl, obwohl sich die Zeichenanzahl nicht ändert?“

Weil die beiden Formen aus verschiedenen Codepunkten aufgebaut sind, die in UTF-8 unterschiedlich viele Bytes kosten. Ein vorkomponiertes é sind zwei Bytes; das zerlegte Paar sind drei. Die Zählertabelle oben gibt alle vier Zahlen für die Eingabe und für jede Form nebeneinander aus, sodass der Unterschied sichtbar und nicht nur beschrieben ist.

„Woher weiß ich, dass die Ergebnisse auf dieser Seite richtig sind?“

Drücken Sie Selbsttest. Er normalisiert jeden Fall in der Datendatei dieser Seite, prüft die vier Formen gegeneinander auf die dokumentierten Beziehungen (NFC ist idempotent, NFD einer NFC-Zeichenfolge ist dasselbe wie NFD des Originals usw.), schickt jedes Zeichen aus den Tabellen für unsichtbare und Steuerzeichen durch den Scanner und zählt die Graphemfälle gegen Intl.Segmenter.

Standards und Quellenangaben

Die vier Formen und ihre Definitionen stammen aus dem Unicode-Standard, Anhang 15 (Unicode Normalization Forms). Die Codepunkte, die als Zerlegungsbeispiele dienen, sind diejenigen, die der Standard vorgibt; diese Seite implementiert die Zerlegungstabellen selbst nicht — sie ruft die eigene String.prototype.normalize des Browsers auf, dieselbe Implementierung, die die Plattform für Texteingabe, Sortierung und Vergleich nutzt. Was hier gemeldet wird, ist also, was der Rest des Systems mit derselben Zeichenfolge tut. Graphem-Cluster stammen aus Intl.Segmenter, wo der Browser es hat, und sonst aus einer dokumentierten Näherung.

Der Seitentext wurde für diese Website geschrieben. Jedes durchgerechnete Beispiel auf dieser Seite wurde vom eigenen Code der Seite erzeugt und dann gegen die aufgezeichnete Fallliste der Datendatei geprüft, die wiederum gegen die NormalizationTest-Daten von Unicode für dieselben Zeichen geprüft wurde. Die Tabellen für unsichtbare und gefährliche Zeichen sind eine kuratierte Auswahl für gut lesbare Warnungen, nicht das vollständige Unicode-Sicherheitsprofil (UTS #39), und die Seite sagt das ausdrücklich, statt eine Vollständigkeit vorzutäuschen, die sie nicht hat.