
Cプログラマーとして、私は長いテキストファイル出力についてwc -c
(バイト計算)とwc -m
(文字計算)の結果が非常に異なることに驚きました。私はいつもsizeof(char)
1バイトだと聞きました。
qdii@nomada ~/Documents $ wc -c sentences.csv
102990983 sentences.csv
qdii@nomada ~/Documents $ wc -m sentences.csv
89023123 sentences.csv
説明がありますか?
答え1
Cのタイプchar
はバイトですが、ASCII文字に対して機能します。可変幅エンコーディングUTF-8などのエンコーディングは、文字ごとに多くのバイトを占めます。環境変数によって設定されたロケールに従ってマルチバイトシーケンスをデコードするには、wc
この関数を使用します。ロケールが正しく設定されると、すべての場合で同じ結果が得られます。たとえば、mbrtowc(3)
LC_CTYPE
qdii@nomada ~/Documents $ LC_CTYPE="C" wc -m sentences.csv
102990983 sentences.csv
答え2
推測されるのは
あなたのロケールはUTF-8エンコーディングを使用します。
ファイル内の文字の約10%は、UTF-8でエンコードするために複数のオクテットが必要です。
ところで、ソースman wc
:
-c, --bytes
print the byte counts
-m, --chars
print the character counts
答え3
最小限の例
「と呼ばれるUnicode文字「é」を考えてみてください。アクセント付きラテン小文字E「これは鋭いアクセント多くのヨーロッパ言語で使用されています。
UTF-8エンコーディングは、2バイト長の「0xc3 0xa9」です。
これを念頭に置いて、私たちは以下を見ています。
printf '\xc3\xa9' | LC_CTYPE=en_US.UTF-8 wc -c
printf '\xc3\xa9' | LC_CTYPE=en_US.UTF-8 wc -m
printf '\xc3\xa9' | LC_CTYPE=C wc -c
printf '\xc3\xa9' | LC_CTYPE=C wc -m
出力:
2
1
2
2
だから私たちは説明どおりに理解しますhttps://unix.stackexchange.com/a/51948/32558正しいUTF-8数を取得するには、wc -m
とが必要ですLC_CTYPE=en_US.UTF-8
。
私のシステムで入力方法を使用してテキストéを入力すると、結果は同じです。
printf 'é' | LC_CTYPE=en_US.UTF-8 wc -c
Ubuntu 21.04でテストされました。