从基础到进阶的完整指南
目录导读
- 功能概述与使用场景
- 核心实现原理
- Shell脚本实战:统计单词、行数、字符数
- Python脚本进阶:多文件合并统计与正则过滤
- 常见问题问答(FAQ)
- 性能优化与日志记录技巧
功能概述与使用场景
统计是脚本开发中最基础且高频的需求之一,无论是运维人员分析日志文件、开发人员统计代码行数,还是文本处理中校验文档完整性,脚本都能快速完成统计任务。

- 统计日志中错误出现的次数
- 计算代码仓库中每种文件的代码行数
- 批量分析CSV文件的行数是否一致
通过脚本实现不仅能避免人工逐篇统计的低效,还能融入自动化流水线,实时生成报告。
核心实现原理
几乎所有统计功能都基于三种底层操作:
- 逐行读取:将文件分解为行流(
while read line或for line in file) - 计数器变量:定义整型变量累加(如
count++) - 条件过滤:通过正则表达式或模式匹配筛选特定内容(如
grep -c)
关键点在于如何平衡内存占用与处理速度,大文件(如GB级日志)应避免 read() 整文件加载,需采用流式读取。
Shell脚本实战:统计单词、行数、字符数
1 基础统计(内置命令)
#!/bin/bash file="access.log" lines=$(wc -l < $file) # 行数 words=$(wc -w < $file) # 单词数 chars=$(wc -m < $file) # 字符数 echo "行数: $lines, 单词数: $words, 字符数: $chars"
2 进阶:统计特定模式出现次数
#!/bin/bash pattern="ERROR" count=$(grep -c "$pattern" $file) echo "错误出现次数: $count"
3 多文件批量统计
#!/bin/bash for f in *.log; do [ -f "$f" ] && echo "$f: $(wc -l < $f) 行" done | sort -t: -k2 -rn
性能提示:当文件包含大量Unicode字符时,wc -m 需配合UTF-8 locale,否则字符统计不准确。
Python脚本进阶:多文件合并统计与正则过滤
Python 在复杂统计场景(如需要跨行匹配、结构化解构)中优势明显。
1 统计目录下所有.log文件的总行数并排除空行
import os
import re
def count_lines_in_folder(folder_path, ext=".log"):
total_lines = 0
for root, dirs, files in os.walk(folder_path):
for file in files:
if file.endswith(ext):
file_path = os.path.join(root, file)
with open(file_path, 'r', encoding='utf-8') as f:
for line in f:
if line.strip(): # 跳过空行
total_lines += 1
return total_lines
print(count_lines_in_folder("/var/log"))
2 使用正则匹配并统计特定字符序列
import re
with open('textfile.txt', 'r') as f:
text = f.read()
# 统计所有形如 "IP:192.168.x.x" 的IP出现次数
ips = re.findall(r'\b(?:192\.168\.\d{1,3}\.\d{1,3})\b', text)
print(f"内网IP出现次数: {len(ips)}")
3 输出格式化统计报告(CSV/JSON)
import csv
report = [("文件", "字符数", "非空白字符数")]
for file in ["a.txt","b.txt"]:
with open(file) as f:
data = f.read()
report.append((file, len(data), len(data.replace(" ","").replace("\n",""))))
with open('stats.csv', 'w', newline='') as csvfile:
writer = csv.writer(csvfile)
writer.writerows(report)
常见问题问答(FAQ)
Q1:为什么用 wc -l 统计的行数比实际行数少1?
A:因为 wc -l 统计的是换行符(\n)的个数,若最后一行没有换行符,显示的行数会少1,解决方案:使用 grep -c '' 或 cat -n 时在文件末尾追加一个空白行后再统计。
Q2:如何统计超大文件(如20GB)的行数而不耗尽内存?
A:Shell脚本天然流式处理,无需额外注意,在Python中则必须使用 for line in open(file):,切忌使用 readlines(),更优方案:使用 mmap 模块映射文件到内存虚拟空间。
Q3:脚本统计时如何忽略注释行和空白行?
A:
- Shell:
grep -v '^#' file | grep -v '^$' | wc -l - Python:添加条件
if line.strip() and not line.startswith('#'):
Q4:能否统计二进制文件中的可读字符?
A:可以,使用 strings 命令提取可读字符串后再 wc,strings binary.bin | wc -w,Python中则用 string.printable 过滤不可打印字符。
性能优化与日志记录技巧
1 并行处理多文件
当需要统计大量文件时,需利用 xargs -P 或 multiprocessing.Pool 并行执行。
Shell示例:
find . -name "*.log" -print0 | xargs -0 -P4 -I {} sh -c 'wc -l "$1"' _ {}
2 统计结果写入日志并添加时间戳
timestamp=$(date "+%Y-%m-%d %H:%M:%S")
echo "[$timestamp] 总计:$(find /app/logs -name "server.log" -exec cat {} + | wc -l) 行" >> stats.log
3 避免重复计算:缓存历史统计
在Python中可使用 pickle 存储文件修改时间与上一次统计值:
import os, pickle
cache = {}
if os.path.exists("cache.pkl"):
with open("cache.pkl","rb") as f:
cache = pickle.load(f)
if os.path.getmtime(file) != cache.get(file+"_mtime"):
# 重新统计并更新缓存
通过以上脚本实现,你可以轻松从简单的行数统计扩展到复杂的模式匹配与批量报告生成,无论是日常运维还是开发测试,掌握这些技巧都能显著提升数据处理效率,深入实践时建议根据文件大小、字符编码和统计粒度灵活选择Shell或Python方案。