Files
my-project/config/openclaw/scripts/novel-learning/novel-format-check.sh
T

342 lines
11 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/bin/bash
# ============================================================================
# 程序名称: novel-format-check.sh
# ============================================================================
# 功能描述: 小说写作规范检查模块,自动校验格式、字数、描写标准
# ============================================================================
# 设计目的:
# 1. 检查章节格式规范(禁止Markdown标题、分隔线等)
# 2. 校验字数标准(5000-8000字)
# 3. 评估描写标准(内心独白、动作描写、对话、环境描写)
# 4. 检查禁止项(沉默良久、省略号、过渡词)
# 5. 生成检查报告并计算总分
# ============================================================================
# 输入参数:
# $1: 章节文件名(可选,默认检查最新章节)
# ============================================================================
# 输出:
# 标准输出: 检查结果
# 文件: ${章节名}-检查报告.md
# ============================================================================
# 依赖:
# - grep, sed, wc, bc
# - /root/.openclaw/workspace/平安书 目录
# ============================================================================
# 作者: 青龙 (OpenClaw AI)
# 创建时间: 2026-02-13
# 更新: 2026-02-13 v1.1 修复逻辑错误
# ============================================================================
# 检查清单:
# [x] 头部注释完整
# [x] grep错误处理 (2>/dev/null)
# [x] 空值处理 ([ -z "$var" ])
# [x] 返回值处理 ($?)
# [x] 语法检查 (bash -n)
# ============================================================================
NOVEL_DIR="/root/.openclaw/workspace/平安书"
TIMESTAMP=$(date '+%Y-%m-%d %H:%M')
# ============================================================================
# 1. 检查格式规范
# ============================================================================
check_format() {
local chapter="$1"
local errors=""
# 检查Markdown标题
if grep -q "^#" "$chapter" 2>/dev/null; then
errors="${errors}❌ 包含Markdown标题\n"
fi
# 检查分隔线
if grep -q "^---" "$chapter" 2>/dev/null; then
errors="${errors}❌ 包含分隔线\n"
fi
# 检查章节小节
if grep -q "^## " "$chapter" 2>/dev/null; then
errors="${errors}❌ 包含章节小节\n"
fi
# 检查章节落款
if grep -qE "第[0-9]+章.*完" "$chapter" 2>/dev/null; then
errors="${errors}❌ 包含章节落款\n"
fi
# 检查**加粗标记(纯文本禁止任何Markdown格式)
if grep -q "\*\*" "$chapter" 2>/dev/null; then
local count=$(grep -c "\*\*" "$chapter")
errors="${errors}❌ 包含${count}处**加粗标记(纯文本禁止Markdown格式)\n"
fi
if [ -z "$errors" ]; then
echo "✅ 格式规范: 通过"
return 0
else
echo "⚠️ 格式规范: 存在问题"
echo -e "$errors"
return 1
fi
}
# ============================================================================
# 2. 检查字数标准
# ============================================================================
check_length() {
local chapter="$1"
# 使用Python精确统计纯汉字数
# wc -m 统计所有字符(含标点),需要去除
local char_count=$(python3 -c "
import sys
with open('$chapter', 'r', encoding='utf-8') as f:
content = f.read()
# 只统计汉字
count = sum(1 for c in content if '\u4e00' <= c <= '\u9fff')
print(count)
" 2>/dev/null)
[ -z "$char_count" ] && char_count=0
echo " 字数统计: $char_count 字"
if [ $char_count -ge 5000 ] && [ $char_count -le 8000 ]; then
echo " ✅ 字数标准: 符合 (5000-8000)"
return 0
elif [ $char_count -lt 5000 ]; then
local diff=$((5000 - char_count))
echo " ⚠️ 字数标准: 不足 (需+$diff字)"
return 1
else
local diff=$((char_count - 8000))
echo " ⚠️ 字数标准: 超出 (需-$diff字)"
return 1
fi
}
# ============================================================================
# 3. 检查描写标准
# ============================================================================
check_description() {
local chapter="$1"
# 内心独白
local inner=$(grep -cE "想道|心中|暗自|默念|忖道" "$chapter" 2>/dev/null)
[ -z "$inner" ] && inner=0
echo " 内心独白: $inner 处"
# 动作描写关键词
local action=$(grep -cE "身形|身形一|伸手|抬手|迈步|纵身|疾驰|飞奔" "$chapter" 2>/dev/null)
[ -z "$action" ] && action=0
echo " 动作描写: $action 处"
# 对话
local dialogue=$(grep -c "「\|”" "$chapter" 2>/dev/null)
[ -z "$dialogue" ] && dialogue=0
dialogue=$((dialogue / 2))
echo " 对话数量: $dialogue 段"
# 环境描写
local env_count=$(grep -cE "天空|山林|月光|风声|树叶|流水" "$chapter" 2>/dev/null)
[ -z "$env_count" ] && env_count=0
echo " 环境描写: $env_count 处"
# 评分
local score=0
if [ $inner -ge 3 ]; then
score=$((score + 25))
echo " ✅ 内心独白: 符合 (≥3)"
else
echo " ⚠️ 内心独白: 不足 (<3)"
fi
if [ $action -ge 3 ]; then
score=$((score + 25))
echo " ✅ 动作描写: 符合 (≥3)"
else
echo " ⚠️ 动作描写: 不足 (<3)"
fi
if [ $dialogue -ge 4 ]; then
score=$((score + 25))
echo " ✅ 对话数量: 符合 (≥4)"
else
echo " ⚠️ 对话数量: 不足 (<4)"
fi
if [ $env_count -ge 5 ]; then
score=$((score + 25))
echo " ✅ 环境描写: 符合 (≥5)"
else
echo " ⚠️ 环境描写: 不足 (<5)"
fi
echo " 📊 描写评分: $score/100"
if [ $score -ge 75 ]; then
return 0
else
return 1
fi
}
# ============================================================================
# 4. 检查禁止项
# ============================================================================
check_prohibited() {
local chapter="$1"
local violations=0
# 沉默良久
local silence=$(grep -c "沉默良久" "$chapter" 2>/dev/null)
[ -z "$silence" ] && silence=0
if [ $silence -gt 2 ]; then
echo " ⚠️ '沉默良久': $silence 次 (应≤2)"
violations=$((violations + 1))
else
echo " ✅ '沉默良久': $silence 次 (≤2)"
fi
# 省略号(中文省略号)
local ellipsis=$(grep -c "……" "$chapter" 2>/dev/null)
[ -z "$ellipsis" ] && ellipsis=0
if [ $ellipsis -gt 5 ]; then
echo " ⚠️ '……': $ellipsis 次 (应≤5)"
violations=$((violations + 1))
else
echo " ✅ '……': $ellipsis 次 (≤5)"
fi
# 过渡段落
local transition=$(grep -cE "不多时|片刻之后|过了一会儿" "$chapter" 2>/dev/null)
[ -z "$transition" ] && transition=0
if [ $transition -gt 3 ]; then
echo " ⚠️ 过渡词: $transition 次 (应≤3)"
else
echo " ✅ 过渡词: $transition 次 (≤3)"
fi
# 返回0表示无违规,返回1表示有违规
if [ $violations -gt 0 ]; then
return 1
else
return 0
fi
}
# ============================================================================
# 5. 生成检查报告
# ============================================================================
generate_report() {
local chapter="$1"
local chapter_name=$(basename "$chapter" .txt)
local report_file="${chapter%.txt}-检查报告.md"
# 如果章节在 NOVEL_DIR 下,报告也要放到 NOVEL_DIR
if [[ "$chapter" == "$NOVEL_DIR"* ]]; then
local base_name=$(basename "$chapter" .txt)
report_file="$NOVEL_DIR/${base_name}-检查报告.md"
fi
# 检查各项
local format_status=0
local length_status=0
local desc_status=0
local prohibited_status=0
check_format "$chapter" || format_status=1
echo ""
check_length "$chapter" || length_status=1
echo ""
check_description "$chapter" || desc_status=1
echo ""
check_prohibited "$chapter" || prohibited_status=1
# 计算总分
local total=4
local passed=$((total - format_status - length_status - desc_status - prohibited_status))
local score=$((passed * 100 / total))
# 生成报告
cat > "$report_file" << MD
# ${chapter_name} - 格式检查报告
**时间**: $TIMESTAMP
**章节**: $chapter_name
## 检查结果
| 项目 | 状态 | 分值 |
|------|------|------|
| 格式规范 | $([ $format_status -eq 0 ] && echo "✅ 通过" || echo "❌ 失败") | $([ $format_status -eq 0 ] && echo "25" || echo "0") |
| 字数标准 | $([ $length_status -eq 0 ] && echo "✅ 通过" || echo "❌ 失败") | $([ $length_status -eq 0 ] && echo "25" || echo "0") |
| 描写标准 | $([ $desc_status -eq 0 ] && echo "✅ 通过" || echo "❌ 失败") | $([ $desc_status -eq 0 ] && echo "25" || echo "0") |
| 禁止项 | $([ $prohibited_status -eq 0 ] && echo "✅ 通过" || echo "❌ 失败") | $([ $prohibited_status -eq 0 ] && echo "25" || echo "0") |
**总分**: $score/100
$(if [ $score -ge 75 ]; then
echo "## ✅ 检查结果: 通过"
else
echo "## ⚠️ 检查结果: 需要改进"
fi)
## 改进建议
$(if [ $format_status -eq 1 ]; then
echo "- 遵守写作标准程序,禁止Markdown标题、分隔线"
fi)
$(if [ $length_status -eq 1 ]; then
echo "- 调整字数至5000-8000字范围"
fi)
$(if [ $desc_status -eq 1 ]; then
echo "- 增加内心独白、动作描写、对话、环境描写"
fi)
$(if [ $prohibited_status -eq 1 ]; then
echo "- 减少禁止使用的表达(沉默良久、省略号、过渡词)"
fi)
---
*自动生成于 $TIMESTAMP*
MD
echo ""
echo "📁 报告: $report_file"
echo "📊 得分: $score/100"
}
# ============================================================================
# 主程序
# ============================================================================
main() {
echo "╔════════════════════════════════════════════════════╗"
echo "║ 小说写作规范检查模块 v1.1 ║"
echo "╚════════════════════════════════════════════════════╝"
echo ""
if [ -z "$1" ]; then
# 检查最新章节
local latest=$(ls -t "$NOVEL_DIR"/*.txt 2>/dev/null | grep -E "[0-9]+章" | head -1)
if [ -z "$latest" ]; then
echo "ℹ️ 未发现章节文件"
exit 1
fi
echo "📖 检查最新章节: $(basename "$latest")"
generate_report "$latest"
else
echo "📖 检查章节: $1"
generate_report "$NOVEL_DIR/$1"
fi
echo ""
echo "✅ 检查完成"
}
main "$@"