概述
在软件开发过程中,代码统计是项目管理和质量评估的重要环节。使用 cloc 工具来进行 Git 代码库的统计分析。
cloc 是一个专门用于统计代码行数的工具,支持多种编程语言,能够区分代码、注释和空行。
安装 cloc
# macOS
brew install cloc
# Ubuntu/Debian
sudo apt-get install cloc
# CentOS/RHEL
sudo yum install cloc
# 或使用Perl CPAN
cpan App::cloc
基本使用
1. 统计当前目录代码
cloc .

2. 统计特定文件类型
cloc --include-lang=JavaScript,TypeScript,Python .

3. 排除特定目录
cloc --exclude-dir=node_modules,dist,build .

4. 生成详细报告
cloc --by-file --report-file=code_stats.txt .
cloc 高级功能
1. 比较两个版本的代码差异
# 比较两个分支
git archive main | cloc --stdin-name=main.tar -
git archive develop | cloc --stdin-name=develop.tar -
# 使用cloc的diff功能
cloc --diff main.tar develop.tar
2. 生成多种格式报告
# CSV格式
cloc --csv --out=stats.csv .
# JSON格式
cloc --json --out=stats.json .
# XML格式
cloc --xml --out=stats.xml .
3. 自定义语言定义
# 创建自定义语言定义文件
cat > my_languages.txt << EOF
Vue
filter remove_matches ^\s*//
filter remove_inline //.*$
filter remove_matches ^\s*/\*
filter remove_matches ^\s*\*
filter remove_matches \*/\s*$
extension vue
3rd_gen_scale 1.00
EOF
# 使用自定义定义
cloc --force-lang-def=my_languages.txt .
Git 集成使用
1. Git Hook 集成
创建 pre-commit hook 来自动生成代码统计:
#!/bin/bash
# .git/hooks/pre-commit
echo "正在生成代码统计报告..."
# 使用cloc生成统计
cloc --quiet --csv . > code_stats.csv
# 统计提交数量
git log --oneline | wc -l > commit_count.txt
echo "代码统计完成"
2. 定期报告脚本
#!/bin/bash
# weekly_report.sh
REPORT_DIR="reports/$(date +%Y-%m-%d)"
mkdir -p "$REPORT_DIR"
echo "生成周报告: $REPORT_DIR"
# cloc统计
cloc --by-file --csv --out="$REPORT_DIR/cloc_report.csv" .
# Git活动统计
git log --since="1 week ago" --pretty=format:"%an" | \
sort | uniq -c | sed 's/^ *\([0-9]*\) \(.*\)/\2,\1/' \
> "$REPORT_DIR/weekly_commits.csv"
# 文件修改热度
git log --since="1 week ago" --name-only --pretty=format: | \
grep -v "^$" | \
sort | uniq -c | sed 's/^ *\([0-9]*\) \(.*\)/\2,\1/' | \
sort -t',' -k2 -nr > "$REPORT_DIR/file_changes.csv"
echo "报告生成完成: $REPORT_DIR"
3. 代码质量监控
#!/bin/bash
# quality_monitor.sh
# 设置阈值
MAX_FILE_LINES=500
MAX_FUNCTION_LINES=50
echo "=== 代码质量监控报告 ==="
# 检查大文件
echo "检查超过 $MAX_FILE_LINES 行的文件:"
cloc --by-file . | tail -n +4 | while read blank comment code file; do
if [ "$code" -gt "$MAX_FILE_LINES" ] 2>/dev/null; then
echo "警告: $file 有 $code 行代码"
fi
done
# 检查复杂度(简单示例)
echo -e "\n检查可能的复杂函数:"
find . -name "*.js" -o -name "*.py" -o -name "*.java" | while read file; do
# 使用grep和wc简单检查函数长度
grep -n "function\|def \|public \|private " "$file" | while IFS=: read line_num func_line; do
# 简化的函数长度检查:查找下一个函数或文件结束
next_func=$(grep -n "function\|def \|public \|private " "$file" | grep -A1 "^$line_num:" | tail -1 | cut -d: -f1)
if [ -z "$next_func" ] || [ "$next_func" = "$line_num" ]; then
next_func=$(wc -l < "$file")
fi
func_length=$((next_func - line_num))
if [ "$func_length" -gt "$MAX_FUNCTION_LINES" ]; then
echo "警告: $file:$line_num 函数可能有 $func_length 行"
fi
done
done
实用脚本示例
1. 项目健康度检查
#!/bin/bash
# project_health.sh
echo "=== 项目健康度检查 ==="
# 代码统计
echo "1. 代码行数统计:"
cloc --quiet .
# 提交频率
echo -e "\n2. 最近30天提交频率:"
total_commits=$(git log --since="30 days ago" --oneline | wc -l)
echo "总提交数: $total_commits"
echo "平均每天: $(echo "scale=2; $total_commits / 30" | bc)"
# 活跃贡献者
echo -e "\n3. 活跃贡献者 (最近30天):"
git log --since="30 days ago" --pretty=format:"%an" | \
sort | uniq -c | sort -nr | while read count author; do
if [ "$count" -ge 5 ]; then
echo "$author: ${count}次提交"
fi
done
# 代码覆盖度(如果有测试)
if [ -d "test" ] || [ -d "tests" ]; then
echo -e "\n4. 测试文件比例:"
total_files=$(find . -name "*.js" -o -name "*.py" -o -name "*.java" | wc -l)
test_files=$(find . -path "*/test*" -name "*.js" -o -path "*/test*" -name "*.py" -o -path "*/test*" -name "*.java" | wc -l)
echo "测试文件: $test_files / $total_files"
echo "测试覆盖率: $(echo "scale=2; $test_files * 100 / $total_files" | bc)%"
fi
2. 技术债务分析
#!/bin/bash
# tech_debt.sh
echo "=== 技术债务分析 ==="
# TODO/FIXME统计
echo "1. TODO/FIXME标记:"
todo_results=$(grep -r -n "TODO\|FIXME\|HACK\|XXX" --include="*.js" --include="*.py" --include="*.java" .)
total_todos=$(echo "$todo_results" | wc -l)
echo "总计: $total_todos 个待办项"
echo "分布:"
echo "$todo_results" | cut -d: -f1 | sed 's|.*/||' | sort | uniq -c | sort -nr | head -20 | \
while read count file; do
echo " $file: $count"
done
# 大文件检查
echo -e "\n2. 大文件检查 (>1000行):"
cloc --by-file . | tail -n +4 | while read blank comment code file; do
if [ "$code" -gt 1000 ] 2>/dev/null; then
echo " $file: $code 行"
fi
done | head -10
# 重复代码检测(简单版本)
echo -e "\n3. 可能的重复代码:"
# 提取所有函数名并查找重复
temp_file=$(mktemp)
find . -name "*.js" -o -name "*.py" | while read file; do
grep -n "function\|def " "$file" | while IFS=: read line_num func_line; do
# 提取函数名
func_name=$(echo "$func_line" | sed -e 's/.*function[[:space:]]*//' -e 's/.*def[[:space:]]*//' -e 's/(.*//' -e 's/[[:space:]]//g')
if [ ${#func_name} -gt 3 ]; then
echo "$func_name:$file:$line_num" >> "$temp_file"
fi
done
done
# 查找重复的函数名
cut -d: -f1 "$temp_file" | sort | uniq -d | while read dup_func; do
echo "可能重复的函数 $dup_func:"
grep "^$dup_func:" "$temp_file" | head -5
done | head -10
rm -f "$temp_file"
原文链接:https://code.ifrontend.net/archives/909,转载请注明出处。
评论0