wc -mとwc -cはなぜ違うのですか?

wc -mとwc -cはなぜ違うのですか?

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

推測されるのは

  1. あなたのロケールはUTF-8エンコーディングを使用します。

  2. ファイル内の文字の約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でテストされました。

関連情報