$ locale charmap
UTF-8
In meiner aktuellen Umgebung ist der Zeichensatz UTF-8, dh Zeichen werden mit 1 bis 4 Bytes pro Zeichen codiert (obwohl die ursprüngliche Definition von UTF-8 zulässigen Zeichencodepunkten bis 0x7fffffff die meisten Tools UTF- 8-Byte-Sequenzen von bis zu 6 Byte).
In diesem Zeichensatz stehen alle Zeichen aus Unicode zur Verfügung, a a
ist beispielsweise als Bytewert 65, a 乕
als 3- é
Byte-Sequenz 228 185 149 und als Zwei-Byte-Sequenz 195 169 codiert .
$ printf 乕 | wc -mc
1 3
$ printf a | wc -mc
1 1
Jetzt:
$ export fr_FR.iso885915@euro
$ locale charmap
ISO-8859-15
Ich habe meine Umgebung geändert, in der der Zeichensatz jetzt ISO-8859-15 ist (andere Dinge wie Sprache, Währungssymbol, Datumsformat wurden ebenfalls geändert, die Sammlung dieser regionalen Einstellungen wird als Gebietsschema bezeichnet ). In dieser Umgebung muss ein neuer Terminal-Emulator gestartet werden, damit die Zeichenwiedergabe an das neue Gebietsschema angepasst werden kann.
ISO-8859-15 ist ein Einzelbyte-Zeichensatz, der nur 256 Zeichen enthält (tatsächlich werden sogar weniger als die tatsächlich abgedeckten Zeichen verwendet). Dieser spezielle Zeichensatz wird für westeuropäische Sprachen verwendet, da er die meisten seiner Sprachen (und das Euro-Symbol) abdeckt.
Es hat das a
Zeichen mit dem Bytewert 65 wie in UTF-8 oder ASCII, es hat auch das é
Zeichen (wie es beispielsweise in Französisch oder Spanisch gebräuchlich ist), aber mit dem Bytewert 233 hat es nicht das Zeichen 乕.
In dieser Umgebung wc -c
und wc -m
wird immer das gleiche Ergebnis geben.
In Ubuntu wie auf den meisten modernen Unix-ähnlichen Systemen ist die Standardeinstellung normalerweise UTF-8, da dies der einzige unterstützte Zeichensatz (und die einzige Codierung) ist, die den gesamten Unicode-Bereich abdeckt.
Es gibt andere Mehrbyte-Zeichenkodierungen, aber sie werden unter Ubuntu nicht so gut unterstützt, und Sie müssen durch die Rahmen gehen, um ein Gebietsschema mit diesen zu generieren, und wenn Sie dies tun, werden Sie feststellen, dass viele Dinge nicht funktionieren richtig arbeiten.
In Ubuntu sind Zeichensätze entweder Einzelbyte- oder UTF-8-Zeichensätze.
Nun noch ein paar Anmerkungen:
In UTF-8 bilden nicht alle Bytefolgen gültige Zeichen. Beispielsweise werden alle UTF-8-Zeichen, die keine ASCII-Zeichen sind, mit Bytes gebildet, für die das 8. Bit gesetzt ist, für die jedoch nur für das erste das 7. Bit gesetzt ist.
Wenn Sie eine Folge von Bytes mit dem 8. Bit gesetzt haben, von denen keines das 7. Bit gesetzt hat, kann dies nicht in ein Zeichen übersetzt werden. Und dann treten Probleme und Inkonsistenzen auf, da die Software nicht weiß, was sie damit anfangen soll. Zum Beispiel:
$ printf '\200\200\200' | wc -mc
0 3
$ printf '\200\200\200' | grep -q . || echo no
no
wc
und grep
finde keinen Charakter darin aber:
$ x=$'\200\200\200' bash -c 'echo "${#x}"'
3
bash
Findet 3. Wenn einem Zeichen keine Folge von Bytes zugeordnet werden kann, wird jedes Byte als Zeichen betrachtet.
Dies kann noch komplizierter werden, da es in Unicode Codepunkte gibt, die als Zeichen ungültig sind, und einige, die keine Zeichen sind. Je nach Tool wird die UTF-8-Codierung möglicherweise als Zeichen betrachtet oder nicht.
Eine andere zu berücksichtigende Sache ist der Unterschied zwischen Charakter und Graphem und wie sie gerendert werden.
$ printf 'e\u301\u20dd\n'
é⃝
$ printf 'e\u301\u20dd' | wc -mc
3 6
Dort haben wir 3 Zeichen als 6 Bytes als ein Graphem gerendert, weil wir 3 Zeichen zusammen haben (ein Basiszeichen, einen kombinierenden Akzent und einen kombinierenden umschließenden Kreis).
Die GNU-Implementierung von wc
as, wie sie unter Ubuntu zu finden ist, verfügt über einen -L
Schalter, der die Anzeigebreite der breitesten Zeile in der Eingabe angibt:
$ printf 'e\u301\u20dd\n' | wc -L
1
Sie werden auch feststellen, dass einige Zeichen in dieser Breitenberechnung 2 Zellen belegen , wie unser 乕
Zeichen von oben:
$ echo 乕 | wc -L
2
Fazit: Im wilden Wort sind Byte, Zeichen und Graphem nicht unbedingt dasselbe.