Linuxの「wc -c」および「wc -m」コマンド


24

テキストファイルがあり、その内容は次のとおりです。

i k k

wc -mこのファイルの文字数を数えるために使用すると、結果は7です。

質問1:しかし、「行末」文字をカウントすると仮定して、なぜ「6」を取得すべきではないのに、なぜ7を取得したのでしょうか?

質問2:正確にどのように機能しwc -mますか?

質問3:私が使用している場合wc -c(バイト数をカウントする)、私は同じ結果を持っているwc -mので、二つの異なるオプションを持つことのポイントは何ですか?彼らはまったく同じ仕事をしていませんか?そうでない場合、違いは何wc -cですか?



1
あなたのファイルは、CRLFの改行コードを使用してWindowsから来た場合にも、7を持っている可能性が
クリス・H

回答:


36

実際、そこには6文字しかありません。実行してみてください

cat -A filename

ファイルの非印刷文字を表示します。余分なものが必要です。あなたと同じようにファイルを作成すると、

i k k$

スペースを入れましたか?それは7になります:i k k $または多分それは改行を持っています:

i k k$
$

これも7

あなたが言うように

wc -m

文字をカウントし、

wc -c

バイトをカウントします。すべての文字がASCII文字セットの一部である場合、文字ごとに1バイトしかないため、両方のコマンドから同じカウントを取得します。

非ASCII文字を含むファイルを試してください:

$ echo ك > testfile
$ wc -m testfile
2 testfile
$ wc -c testfile
3 testfile

あぁ!現在、文字よりも多くのバイト。


3
cat -A」コマンドを使用したところ、「行末」文字($)の前にスペースが1つあることがわかりました。6の代わりに7を得たのはそのためです。ありがとう、「cat -A」は大いに役立ちました。
SWIIWII

2
@SWIIWIIええ、私はおそらくそれだろうと思ったので、答えにそれを追加しました:)
Zanna

1
改行文字もカウントされました。たとえ見えなくても、それは文字であり、ファイル内のデータの塊としてカウントされます。ちなみに猫-Aをよく使う。かつてhexdumpまたはxxdを使用して同じことを行うこともできました
Sergiy Kolodyazhnyy

@Sergはい、cat -Aそれも表示されます。私は答えに追加しました、ありがとう:)
ザンナ

@SWIIWIIはコードを`likethis`読みやすくするためにバックティックに入れ、太字にしないでください
-phuclv

2
$ 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文字しかありません(実際には、実際にカバーされている文字よりもさらに少ない)。その特定の文字セットは、ほとんどの言語(およびユーロ記号)をカバーするため、西ヨーロッパの言語に使用されます。

それは持っているaUTF-8またはASCIIで、それも持っているようなバイト値65の文字é文字を(一般的例えばフランス語やスペイン語で使用される)が、バイト値233と、それは乕文字を持っていません。

その環境ではwc -cwc -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つのグラフェンとしてレンダリングしました。

wcUbuntu のGNU実装に-Lは、入力の最も広い行の表示幅を示すスイッチがあります。

$ printf 'e\u301\u20dd\n' | wc -L
1

また、上記のキャラクターのように、一部のキャラクターがその幅の計算で2つのセルを占有していることもわかります

$ echo 乕 | wc -L
2

結論として、より自然な言葉では、バイト、文字、グラフェンは必ずしも同じではありません。


1

との違いはwc -cwc -mマルチバイト文字(UTF8など)のロケールでは、前者はバイトをカウントし、後者は文字をカウントすることです。次のファイルを検討してください。

$ hexdump -C dummy.txt 
00000000  78 79 cf 80 0a                                    |xy...|

(UTF8を話さない人にとっては、文字 'x'、 'y'、および 'π'の後に改行が続きます)。長さは5バイトです。

$ wc -c dummy.txt 
5 dummy.txt

ただし、4文字のみです。

$ wc -m dummy.txt 
4 dummy.txt

または、すべての文字が4バイトであるUTF-32を検討してください。
ヨルグWミットタグ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.