我有一个文本文件,其内容是:
i k k
当我wc -m
用来计算此文件上的字符数时,结果为7。
问题1:但是为什么我得到7,为什么我不应该假定它计算“ 行尾 ”字符而得到“ 6 ” 呢?
问题2:wc -m
工作原理如何?
问题3:使用wc -c
(计算字节数)时,我得到的结果与相同wc -m
,那么拥有两个不同选项的意义何在?他们做的完全一样,不是吗?如果没有,有什么区别,如何wc -c
运作?
我有一个文本文件,其内容是:
i k k
当我wc -m
用来计算此文件上的字符数时,结果为7。
问题1:但是为什么我得到7,为什么我不应该假定它计算“ 行尾 ”字符而得到“ 6 ” 呢?
问题2:wc -m
工作原理如何?
问题3:使用wc -c
(计算字节数)时,我得到的结果与相同wc -m
,那么拥有两个不同选项的意义何在?他们做的完全一样,不是吗?如果没有,有什么区别,如何wc -c
运作?
Answers:
实际上,那里确实应该只有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
啊哈!现在,字节多于字符。
cat -A
也会显示出来。我添加了我的答案,谢谢:)
`likethis`
以使其可读,而不要使其粗体
$ locale charmap
UTF-8
在我当前的环境中,字符集为UTF-8,即每个字符用1到4个字节进行编码(尽管由于UTF-8的原始定义允许字符代码指向0x7fffffff,所以大多数工具会识别UTF- 8个字节的序列,最多6个字节)。
在该字符集中,所有来自Unicode的字符都是可用的,例如a a
被编码为字节值65 ,a 被编码为乕
3个字节228 185 149和é
两个字节序列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(语言,货币符号,日期格式等其他内容也已修改,这些区域设置的集合称为locale)。我需要在该环境中启动一个新的终端模拟器,以使其字符渲染适应新的语言环境。
ISO-8859-15是单字节字符集,这意味着它只有256个字符(实际上比实际覆盖的字符还要少)。该特定字符集用于西欧语言,因为它涵盖了其大部分语言(和欧元符号)。
它具有a
字符值(如UTF-8或ASCII中的字节值65),也具有é
字符(例如,在法语或西班牙语中通常使用的字符),但具有字节值233,则不具有乕字符。
在那种环境下,wc -c
并且wc -m
将始终给出相同的结果。
在像大多数现代Unix系统一样的Ubuntu中,默认值通常是UTF-8,因为它是覆盖整个Unicode范围的唯一受支持的字符集(和编码)。
还存在其他多字节字符编码,但是在Ubuntu上并没有很好地支持它们,因此您必须经过箍才能使用它们生成语言环境,如果这样做,您会发现很多事情不好好工作。
因此,对于Ubuntu而言,字符集要么是单字节,要么是UTF-8。
现在,更多注意事项:
在UTF-8中,并非所有字节序列都形成有效字符。例如,所有不是ASCII字符的UTF-8字符都是由字节组成的,这些字节都设置了第8位,但是只有第一个设置了第7位。
如果您将字节序列的第8位设置为1,而没有一个字节序列将第7设置为1,则无法将其转换为字符。那就是当您开始遇到问题和不一致时,因为软件不知道该如何处理。例如:
$ 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.当无法将字节序列映射到字符时,它将每个字节视为一个字符。
它可以变得更加复杂,因为有在Unicode代码点是为字符无效,有的认为是无字,并根据工具,他们的UTF-8编码可能会或可能不会被视为一个字符。
要考虑的另一件事是字符和字素之间的区别,以及它们的呈现方式。
$ printf 'e\u301\u20dd\n'
é⃝
$ printf 'e\u301\u20dd' | wc -mc
3 6
在那里,我们将3个字符编码为6个字节,作为一个graphem进行渲染,因为我们将3个字符组合在一起(一个基本字符,一个组合的重音符号和一个组合的围圈)。
wc
在Ubuntu上找到的GNU实现有一个-L
开关来告诉您输入中最宽行的显示宽度:
$ printf 'e\u301\u20dd\n' | wc -L
1
您还会发现一些字符在宽度计算中占据了2个像元,就像我们乕
上面的字符一样:
$ echo 乕 | wc -L
2
结论:在荒野的单词中,字节,字符和字素不一定相同。