Unicode-Zeichen-Inspektor
Zerlegt Text in seine Codepunkte mit Namen, Kategorien, Blöcken und Kodierungen und markiert unsichtbare, Bidi- und Doppelgängerzeichen.
Was dieses Werkzeug tut
Fügen Sie beliebigen Text ein, und er kommt zerlegt in die einzelnen Zeichen zurück, aus denen er wirklich besteht. Jedes erhält seinen Unicode-Namen, seine U+-Nummer, welche Art von Zeichen es ist, zu welchem Schriftsystem und welchem Block es gehört, die Bytes, die es in UTF-8 und UTF-16 belegt, und die Maskierung, die es in sechs verschiedenen Formaten braucht.
Die meisten kommen hierher, weil etwas nicht aufgeht. Eine Zeichenkette ist länger, als sie aussieht, zwei Werte, die identisch angezeigt werden, weigern sich gleich zu sein, ein Benutzername wurde wegen Zeichen abgelehnt, die wie gewöhnliche Buchstaben aussehen, oder eine Zeile Quelltext liest sich anders, als sie sich verhält. Alle vier haben dieselbe Form: ein Zeichen, das etwas tut, was der Bildschirm nicht zeigt.
Zeichen, Codepunkte und Grapheme
Das Wort „Zeichen“ bedeutet mindestens drei verschiedene Dinge, und sie zu verwechseln ist der Anfang fast aller Verwirrung um Unicode. Ein Codepunkt ist ein Wert im Unicode-Standard, geschrieben U+0041 oder U+1F600. Ein Graphem ist das, was ein Leser als ein Zeichen zählt. Häufig sind das nicht dieselben Zahlen.
- Ein schlichtes „a“ ist 1 Graphem, 1 Codepunkt und 1 UTF-16-Einheit — alles stimmt überein.
- U+00E9, das vorkomponierte é, ist 1 Graphem, 1 Codepunkt und 1 UTF-16-Einheit.
- U+0065 U+0301, derselbe Buchstabe als e plus kombinierender Akzent geschrieben, ist 1 Graphem, aber 2 Codepunkte und 2 UTF-16-Einheiten.
- U+1F600, das grinsende Gesicht, ist 1 Graphem und 1 Codepunkt, aber 2 UTF-16-Einheiten — es liegt oberhalb der BMP, also speichert JavaScript es als Ersatzzeichenpaar.
- Das Familien-Emoji ist 1 Graphem, 5 Codepunkte und 8 UTF-16-Einheiten: drei Personen, verbunden durch zwei unsichtbare Verbinder.
Das Familien-Emoji ist der Fall, der die Leute erwischt. Es sieht aus wie eine Sache, JavaScript meldet die Länge 8, und eine Datenbankspalte für 5 Zeichen fasst es nicht. Dieses Werkzeug gruppiert Codepunkte unter dem Graphem, das sie bilden, sodass beide Lesarten gleichzeitig sichtbar sind, statt im Kopf zusammengebracht werden zu müssen.
Die Zeichen, die Sie nicht sehen können
Erstaunlich viele Unicode-Zeichen zeichnen überhaupt nichts. Sie existieren, um zu steuern, wie sich der Text um sie herum verhält, und weil sie keine Spur hinterlassen, überstehen sie Kopieren, Einfügen und Review, ohne dass es jemand bemerkt. Auf diese weist das Werkzeug hin, statt sie bloß aufzulisten:
- Nullbreiten-Leerzeichen, -Verbinder und -Trenner (U+200B, U+200D, U+200C) — keine Breite, keine Spur, und sie brechen jeden Zeichenkettenvergleich, den sie berühren.
- Weiches Trennzeichen (U+00AD) — ein Vorschlag, wo ein Wort umbrechen darf, unsichtbar bis es das tut.
- Geschütztes Leerzeichen (U+00A0) — sieht genau wie ein Leerzeichen aus und ist ein anderes Zeichen, weshalb es sich so lange in Konfigurationsdateien hält.
- Byte-Reihenfolge-Marke (U+FEFF) — bleibt oft am Dateianfang stehen, wo sie zum unsichtbaren ersten Zeichen des ersten Werts wird.
- Bidi-Steuerzeichen und -Überschreibungen (U+202A bis U+202E, U+2066 bis U+2069) — sie ordnen den Text um sich herum um.
Die Bidi-Steuerzeichen verdienen eine eigene Erwähnung. Sie wurden hinzugefügt, damit Hebräisch und Arabisch korrekt mit lateinischem Text gemischt werden können, und diese Aufgabe erfüllen sie gut. Aber eine Überschreibung in einem Kommentar oder einem Zeichenkettenliteral kann eine Zeile Quelltext in einer völlig anderen Reihenfolge anzeigen lassen als der Compiler sie liest — was bedeutet, dass ein Reviewer Code freigeben kann, der etwas ganz anderes tut. Diese Art Trick ist als Trojan Source bekannt, und deshalb kennzeichnet dieses Werkzeug jedes Bidi-Steuerzeichen getrennt von den übrigen unsichtbaren Zeichen.
Doppelgängerzeichen und gemischte Schriften
Unicode enthält viele Zeichen, die ASCII-Buchstaben optisch gleichen und keine sind. Das kyrillische а, das griechische ο und das lateinische a belegen verschiedene Codepunkte und werden in den meisten Schriftarten gleich dargestellt. Eine Domain oder ein Benutzername, der aus ihnen gebaut ist, sieht richtig aus und zeigt woandershin.
Jeden nicht-ASCII-Doppelgänger zu markieren wäre nutzlos: Es würde jedes russische, griechische oder hebräische Wort rot färben, und eine Warnung, die bei gewöhnlichem Text anschlägt, ist eine Warnung, die man zu überlesen lernt. Die Regel hier ist deshalb die des Unicode-Sicherheitsstandards — ein Wort ist verdächtig, wenn die Buchstaben darin aus mehr als einem Schriftsystem stammen:
- „paypal.com“ vollständig in lateinischen Buchstaben: dazu ist nichts zu sagen.
- Dasselbe Wort mit einem kyrillischen er und a vor dem lateinischen „ypal“: ein Wort, zwei Schriftsysteme, markiert.
- Ein ganzes russisches Wort in Kyrillisch: ein Schriftsystem, gewöhnlicher Text, nicht markiert.
- Ein japanischer Satz mit Han, Hiragana und Katakana zugleich: drei Schriften, ein Schriftsystem, nicht markiert.
Dieser letzte Fall ist der Grund, warum die Regel Sorgfalt verlangt. Japanisch wird mit drei Schriften zugleich geschrieben und Koreanisch mischt zwei, sodass ein naiver Test nach dem Muster „mehr als eine Schrift ist verdächtig“ jeden japanischen Satz zum Angriff erklären würde. Die Kombinationen, die wirklich ein Schriftsystem sind, werden als eines behandelt, und das hält die Warnung aussagekräftig.
Normalisierung, oder warum zwei identische Zeichenketten sich unterscheiden
Manche Zeichen lassen sich auf mehr als eine Weise schreiben. Der Buchstabe é ist entweder der einzelne Codepunkt U+00E9 oder das Paar U+0065 U+0301 — ein schlichtes e gefolgt von einem kombinierenden Akut. Beide werden identisch dargestellt. Keines ist falsch. Gleich sind sie nicht.
Normalisierung ist der Vorgang, sich für eine Schreibweise zu entscheiden, und davon gibt es vier Formen. NFC komponiert, wo es geht, und ist das, was das Web standardmäßig annimmt; NFD zerlegt stattdessen. Die beiden K-Formen gehen weiter und falten zusätzlich Kompatibilitätszeichen — aus dem Vollbreiten-A wird ein schlichtes A, aus der Ligatur fi wird fi — was für Suche und Abgleich nützlich und für Speicherung verlustbehaftet ist.
Das Feld hier zeigt alle vier Formen dessen, was Sie einfügen, und markiert, welche davon von der Eingabe abweichen. Weicht keine ab, ist der Text bereits normalisiert und die Abweichung, der Sie nachjagen, liegt anderswo. Weichen manche ab, haben Sie sie gefunden.
Namen, Kategorien, Schriften und Blöcke
Jedes zugewiesene Zeichen trägt vier Identitätsangaben, und sie beantworten verschiedene Fragen. Der Name ist das Zeichen selbst. Die allgemeine Kategorie sagt, was für ein Ding es ist — ein Kleinbuchstabe, eine kombinierende Marke, ein Währungssymbol, ein Formatierungssteuerzeichen. Die Schrift ist das Schriftsystem, zu dem es gehört. Der Block ist der Codepunktbereich, in dem es zugewiesen wurde, was eine organisatorische und keine sprachliche Tatsache ist.
Block und Schrift werden leicht verwechselt und stimmen oft nicht überein. Lateinische Buchstaben leben in mindestens einem halben Dutzend Blöcken, und ein Block kann Zeichen mehrerer Schriften enthalten. Wenn Sie wissen wollen „welches Alphabet ist das“, ist die Schrift die Antwort; wenn Sie wissen wollen „wo im Standard steht das“, ist es der Block.
Namen, Schriften und Blöcke werden hier in jeder Sprache bewusst auf Englisch angezeigt. Es sind vom Standard definierte Bezeichner, keine Prosa — U+200D heißt weltweit ZERO WIDTH JOINER, und eine Übersetzung machte es unauffindbar.
Kodierungen und Maskierungen
Ein Codepunkt ist eine Zahl; zu Bytes wird er erst, wenn eine Kodierung gewählt ist. UTF-8 nutzt ein bis vier Bytes und lässt ASCII unverändert, weshalb es sich durchgesetzt hat. UTF-16 nutzt eine oder zwei 16-Bit-Einheiten, und daraus bestehen JavaScript-Zeichenketten — weshalb .length für ein einzelnes Emoji 2 meldet.
U+0041 41 # UTF-8: ein Byte, wie in ASCII U+00E9 C3 A9 # UTF-8: zwei Bytes U+20AC E2 82 AC # UTF-8: drei Bytes U+1F600 F0 9F 98 80 # UTF-8: vier Bytes
Jede Zeile hier gibt das Zeichen außerdem als Maskierung für JavaScript, JSON, HTML, CSS, URLs und Python aus, fertig zum Kopieren. Die sind nicht alle gleich, und oberhalb der BMP zählt der Unterschied: JavaScript und Python haben eine Codepunkt-Maskierung und nutzen sie, während JSON keine hat und ein Emoji als seine beiden Ersatzzeichenhälften buchstabieren muss.
Häufig gestellte Fragen
- Warum ist meine Zeichenkette länger als die Zahl der Zeichen, die ich sehe?
- Entweder enthält sie unsichtbare Zeichen, oder sie enthält Grapheme aus mehreren Codepunkten. Beides wird hier gezeigt: Unsichtbare Zeichen werden markiert, und Grapheme aus mehreren Codepunkten werden gruppiert, sodass Sie das eine Zeichen und die mehreren Werte sehen, aus denen es besteht.
- Zwei Zeichenketten sehen identisch aus und sind nicht gleich. Warum?
- Meist Normalisierung. Ein Buchstabe mit Akzent kann ein Codepunkt sein oder ein Buchstabe plus eine kombinierende Marke, und beide werden gleich dargestellt. Fügen Sie jede Zeichenkette hier ein und vergleichen Sie die Codepunktlisten, oder sehen Sie nach, welche Normalformen von der Eingabe abweichen.
- Was ist ein Nullbreiten-Leerzeichen und wie kam es in meinen Text?
- Es ist ein Zeichen ohne Breite und ohne Spur, das eine Umbruchgelegenheit vorschlägt. Es kommt meist beim Kopieren von Text aus einer Webseite, einem Textverarbeitungsprogramm oder einem Chat-Client herein, und weil nichts angezeigt wird, übersteht es jede Prüfung, bis irgendwo Zeichenketten verglichen werden und es schiefgeht.
- Was ist der Unterschied zwischen einem Codepunkt und einem Zeichen?
- Ein Codepunkt ist ein Unicode-Wert. Ein Zeichen im Alltagssinn ist ein Graphem — was ein Leser als eines zählt — und ein Graphem kann mehrere Codepunkte umfassen. Ein Familien-Emoji sind fünf Codepunkte und ein Graphem.
- Warum sagt das Werkzeug, manche Zeichen hätten keinen Namen?
- Aus vier verschiedenen Gründen, und es sagt, aus welchem. Ersatzzeichen und Codepunkte zur privaten Nutzung haben im Standard keinen Namen, nicht zugewiesene haben nichts zu benennen, und ein Zeichen aus einem selten nachgeschlagenen historischen Block hat einen Namen, den dieser Build nicht mitbringt: Die Namenstabelle behält die Blöcke, aus denen tatsächlich eingefügt wird, statt alle auszuliefern.
- Ist eine Warnung über gemischte Schriften der Beweis für einen Angriff?
- Nein. Sie besagt, dass ein einzelnes Wort seine Buchstaben aus mehr als einem Schriftsystem bezieht, was die Form eines gefälschten Namens ist und was gewöhnlicher Text gelegentlich auch tut. Sie ist ein Grund hinzusehen, kein Urteil.
- Wird etwas von dem, was ich einfüge, an einen Server gesendet?
- Nein. Die Zeichendatenbank wird mit der Seite geladen und alles läuft in Ihrem Browser; nichts, was Sie tippen, wird hochgeladen oder protokolliert, und es funktioniert ohne Netzverbindung.