最近我在对个人日记本系统进行一次升级维护,目标是为目录页新增字数统计功能。这个系统基于Python开发,其核心流程包括:遍历当前目录下的所有txt文件,依据文件名(即日记的创建日期)排序,并按月份归类,最后结合HTML模板生成静态目录页面。
最初为了实现便捷,我在代码中大量依赖Linux shell命令来完成部分操作,例如通过shell指令获取文件列表与基本信息。
ls
初识字数统计工具:wc 命令
熟悉Linux的人大多了解 wc 指令,全称为 word count,常用于统计文本的行数、单词数和字节数。以下是来自Linux manual page的相关说明:
NAME
wc - print newline, word, and byte counts for each
file
SYNOPSIS
wc [OPTION]... [FILE]...
wc [OPTION]... --files0-from=F
DESCRIPTION
Print newline, word, and byte counts for each FILE,
and a total line if more than one FILE is
specified. A word is a nonempty sequence of non
white space delimited by white space characters or
by start or end of input.
With no FILE, or when FILE is -, read standard
input.
The options below may be used to select which
counts are printed, always in the following order:
newline, word, character, byte, maximum line
length.
在实际应用中,比如生信分析流程里,我们经常使用:
wc -l filename.txt # 统计行数
wc -l <file>
或者:
wc -c filename.txt # 统计字节数
wc -c <file>
以及:
wc -w filename.txt # 统计单词数
wc -w <file>
然而这些选项并不适用于我们的需求——因为日记内容主要由UTF-8编码的中文字符构成,同时夹杂数字和英文字母。而 wc -c 统计的是总字节数,一个中文字符通常占3个字节,这会导致结果严重偏高。
wc -c
寻找正确的字符统计方式
那么,如何才能准确地统计字符数量呢?
查阅 wc 的manual page后发现,它其实支持一个关键参数:
wc
-m
-m
该参数的作用是“print the character count”,也就是统计字符个数,理论上正好符合我们的需求。
-m, --chars
print the character counts
以北宋词人柳永的《蝶恋花》为例:
~/sd/termux $ cat test.txt
蝶恋花·伫倚危楼风细细
柳永〔宋代〕
伫倚危楼风细细,望极春愁,黯黯生天际。草色烟光残照里, 无言谁会凭阑意。
拟把疏狂图一醉,对酒当歌,强乐还无味。衣带渐宽终不悔, 为伊消得人憔悴。
~/sd/termux $ wc test.txt
4 4 265 test.txt
~/sd/termux $ wc -m test.txt
92 test.txt
~/sd/termux $
整首词包含标题与标点共92个字符。若直接运行 wc -c,会得到265字节的结果,显然错误;但使用 wc -m 后,输出的字符数则完全正确。
wc -m
问题再现:自动化环境中的统计偏差
正当我以为只需将 wc -m 引入Python模块即可收工时,第二天却发现服务器自动生成的统计结果依然不准确。
原因在于:这套日记系统每天通过Linux的cron服务自动扫描更新一次目录。而在crontab执行环境中,默认可能缺少完整的locale配置,导致系统使用C locale模式运行命令。在这种模式下,wc -m 实际上仍按字节处理多字节字符(如中文),从而造成误判。
经过AI提示,我了解到有两种解决方案:
- 在crontab中显式设置正确的locale环境变量;
- 改用Python内置方法进行字符统计,避免依赖外部命令和系统环境。
出于调试便利考虑,我先尝试了第一种方案。
(base) cyclin@vm:~$ LANG=C.UTF-8 wc -m test.txt
92 test.txt
(base) cyclin@vm:~$ LANG=C wc -m test.txt
265 test.txt
LANG 环境变量的影响
实验表明,在调用 wc 前设置适当的LANG值至关重要:
LANG
不同的 LANG 设置会影响 wc -m 对字符的识别能力。在本地Termux环境中多数设置都能正常工作,但在远程服务器(Ubuntu 22.04)上,只有当设定为:
LANG=en_US.UTF-8
LANG=C.UTF-8
时,wc -m 才能正确解析中文字符。
wc -m
最终推荐命令
综上所述,若希望在Linux环境下可靠地统计包含中文的文本字符数,应使用如下格式的命令:
LANG=C.UTF-8 wc -m <file>
LANG=en_US.UTF-8 wc -m filename.txt
后续优化:转向纯Python实现
在完成上述探索后,DeepSeek建议我从性能与安全角度出发,逐步淘汰对shell命令的依赖。推荐使用Python原生的文件操作接口来替代shell调用,例如:
os.listdir()—— 安全读取目录文件列表os.listdiropen().read()—— 直接读取内容并计算字符数file.read
于是我重构了相关代码。结果显示,每次扫描耗时从原来的5秒以上降至不足3秒,效率提升显著。
小结
整个过程不仅解决了字符统计的问题,也促使我对系统架构进行了更深层次的优化。此外,在统计完成后我才意识到,几年积累下来的日记竟然已突破百万字——没想到我在文字表达上如此“话痨”,不禁莞尔一笑。


雷达卡


京公网安备 11010802022788号







