$ locale charmap
UTF-8
私の現在の環境では、文字セットはUTF-8です。つまり、文字は1文字あたり1〜4バイトでエンコードされます(ただし、UTF-8の元の定義では文字コードが0x7fffffffまでを指すため、ほとんどのツールはUTF-最大6バイトの8バイトシーケンス)。
その文字セットでは、Unicodeのすべての文字が利用でき、a a
はバイト値65、a 乕
は3バイト228 185 149、2 é
バイトシーケンス195 169 などとしてコード化されます。
$ printf 乕 | wc -mc
1 3
$ printf a | wc -mc
1 1
今:
$ export fr_FR.iso885915@euro
$ locale charmap
ISO-8859-15
現在、文字セットがISO-8859-15である環境を変更しました(言語、通貨記号、日付形式などの他のものも変更されており、これらの地域設定のコレクションはロケールと呼ばれています)。その環境で新しいターミナルエミュレータを起動して、その文字レンダリングを新しいロケールに適合させる必要があります。
ISO-8859-15はシングルバイト文字セットです。つまり、256文字しかありません(実際には、実際にカバーされている文字よりもさらに少ない)。その特定の文字セットは、ほとんどの言語(およびユーロ記号)をカバーするため、西ヨーロッパの言語に使用されます。
それは持っているa
UTF-8またはASCIIで、それも持っているようなバイト値65の文字é
文字を(一般的例えばフランス語やスペイン語で使用される)が、バイト値233と、それは乕文字を持っていません。
その環境ではwc -c
、wc -m
常に同じ結果が得られます。
ほとんどの最新のUnixライクシステムのようなUbuntuでは、Unicode範囲全体をカバーする唯一のサポートされる文字セット(およびエンコード)であるため、デフォルトは通常UTF-8です。
他のマルチバイト文字エンコーディングも存在しますが、Ubuntuではあまりサポートされておらず、それらを使用してロケールを生成できるようにするためにフープを通過する必要があります。正しく機能します。
したがって、Ubuntuで有効な文字セットは、シングルバイトまたはUTF-8です。
さて、さらにいくつかのメモ:
UTF-8では、すべてのバイトシーケンスが有効な文字を形成するわけではありません。たとえば、ASCII文字ではないすべてのUTF-8文字は、すべて8ビット目が設定されているバイトで形成されますが、最初の文字のみに7ビット目が設定されています。
8番目のビットが設定されたバイトシーケンスがあり、そのいずれにも7番目のビットが設定されていない場合、文字に変換できません。そして、ソフトウェアがそれらをどうするか分からないので、あなたは問題と矛盾を抱え始めています。例えば:
$ printf '\200\200\200' | wc -mc
0 3
$ printf '\200\200\200' | grep -q . || echo no
no
wc
そしてgrep
そこに何の文字を見つけないが。
$ x=$'\200\200\200' bash -c 'echo "${#x}"'
3
bash
3.一連のバイトを文字にマップできない場合、各バイトを文字と見なします。
文字として無効であるユニコードでコードポイントがあるように、それはさらに複雑になることができ、かつであること、いくつかの非文字、およびツールに依存するが、彼らのUTF-8エンコーディングは、文字として考えてもしなくてもよいです。
考慮すべきもう1つのことは、文字と書記法の違いと、それらのレンダリング方法です。
$ printf 'e\u301\u20dd\n'
é⃝
$ printf 'e\u301\u20dd' | wc -mc
3 6
そこで、3つの文字が結合されているため(1つの基本文字、結合する鋭アクセント、結合する囲み円)、3つの文字を6バイトとして1つのグラフェンとしてレンダリングしました。
wc
Ubuntu のGNU実装に-L
は、入力の最も広い行の表示幅を示すスイッチがあります。
$ printf 'e\u301\u20dd\n' | wc -L
1
また、上記のキャラクターのように、一部のキャラクターがその幅の計算で2つのセルを占有していることもわかります乕
。
$ echo 乕 | wc -L
2
結論として、より自然な言葉では、バイト、文字、グラフェンは必ずしも同じではありません。