This commit is contained in:
owenchen committed 2026-06-22 17:02:13 +08:00
1 parent 44ed43516e
commit 996bb243df
5 files changed
+56 -72

No files matched your search

+38 -40
View File
@@ -18,7 +18,7 @@ namespace CloudBuilder.AI.Utility
// 动态生成的正则表达式(匹配所有配置的引号类型)
private Regex _dynamicQuotePattern;
// 引号内必须包含的结尾标点集合
private readonly string _endPunctuations = "?!。,;:、……~·";
private readonly string _endPunctuations = "?!.,;:?!。,;:、……~·";
/// <summary>
/// 默认构造函数:初始化常用成对引号(中文、英文、直角引号)
@@ -48,47 +48,31 @@ namespace CloudBuilder.AI.Utility
/// <summary>
/// 初始化动态正则:根据配置的成对引号生成匹配规则
/// </summary>
//private void InitDynamicRegex()
//{
// if (_quotePairs.Count == 0)
// {
// // 空配置时生成空正则,避免匹配任何内容
// _dynamicQuotePattern = new Regex(@"^$", RegexOptions.Compiled);
// return;
// }
// // 步骤1:转义所有引号(避免正则特殊字符冲突),拼接左/右引号匹配组
// string escapedLeftQuotes = string.Join("|", _quotePairs.Select(p => Regex.Escape(p.LeftQuote)));
// string escapedRightQuotes = string.Join("|", _quotePairs.Select(p => Regex.Escape(p.RightQuote)));
// // 步骤2:转义标点集合,避免正则解析错误
// string escapedPunctuations = Regex.Escape(_endPunctuations);
// // 步骤3:构建动态正则表达式
// // 分组说明:
// // ?<left>:匹配配置的任意左引号
// // ?<content>:匹配引号内的内容(必须以指定标点结尾)
// // ?<right>:匹配配置的任意右引号
// string regexPattern = $@"(?<left>{escapedLeftQuotes})(?<content>.+?[{escapedPunctuations}])(?<right>{escapedRightQuotes})";
// _dynamicQuotePattern = new Regex(regexPattern, RegexOptions.Compiled | RegexOptions.Singleline);
//}
private void InitDynamicRegex()
{
if (_quotePairs.Count == 0)
{
// 空配置时生成空正则,避免匹配任何内容
_dynamicQuotePattern = new Regex(@"^$", RegexOptions.Compiled);
return;
}
// 步骤1:转义所有引号(避免正则特殊字符冲突),拼接左/右引号匹配组
string escapedLeftQuotes = string.Join("|", _quotePairs.Select(p => Regex.Escape(p.LeftQuote)));
string escapedRightQuotes = string.Join("|", _quotePairs.Select(p => Regex.Escape(p.RightQuote)));
// 步骤2:转义标点集合,避免正则解析错误
string escapedPunctuations = Regex.Escape(_endPunctuations);
// ✅ 修复:移除必须以标点结尾的限制,匹配任意引号内容
string regexPattern = $@"(?<left>{escapedLeftQuotes})(?<content>.+?)(?<right>{escapedRightQuotes})";
// 步骤3:构建动态正则表达式
// 分组说明:
// ?<left>:匹配配置的任意左引号
// ?<content>:匹配引号内的内容(必须以指定标点结尾)
// ?<right>:匹配配置的任意右引号
string regexPattern = $@"(?<left>{escapedLeftQuotes})(?<content>.+?[{escapedPunctuations}])(?<right>{escapedRightQuotes})";
_dynamicQuotePattern = new Regex(regexPattern, RegexOptions.Compiled | RegexOptions.Singleline);
}
/// <summary>
/// 核心分割方法:按配置的成对引号分割文本,结果无引号字符
/// </summary>
@@ -182,15 +166,12 @@ namespace CloudBuilder.AI.Utility
/// <returns>true=包含对话,false=纯旁白/空文本</returns>
public bool IsDialogue(string text)
{
// 1. 处理空文本/NULL,直接返回false
if (string.IsNullOrWhiteSpace(text))
return false;
// 2. 文本预处理:去空格、统一全角/半角引号
string cleanedText = text.Trim();
// 替换全角空格为半角,避免干扰判断
cleanedText = Regex.Replace(cleanedText, @" ", " ");
// 统一引号格式(中文弯引号、直引号 → 标准双引号)
// 统一引号
cleanedText = cleanedText.Replace("“", "\"")
.Replace("”", "\"")
.Replace("〝", "\"")
@@ -200,17 +181,34 @@ namespace CloudBuilder.AI.Utility
.Replace("‘", "'")
.Replace("’", "'");
// 3. 核心判断规则:
var hasQuote = Regex.IsMatch(cleanedText, @""".+?""") ||
Regex.IsMatch(cleanedText, @"[::,,]\s*"""); // 冒号/逗号+引号(说话标记)
// 1. 存在说话引导标记(冒号/逗号 + 引号)
bool hasDialogueTag = Regex.IsMatch(cleanedText, @"[::,,]\s*""");
var hasSingleQuote = Regex.IsMatch(cleanedText, @"'[^']+'");
// 2. 提取所有双引号内容,逐个判断是否为有效对话
var quotedMatches = Regex.Matches(cleanedText, @"""(?<content>.*?)""");
bool hasValidDialogue = false;
foreach (Match m in quotedMatches)
{
string content = m.Groups["content"].Value.Trim();
if (string.IsNullOrEmpty(content)) continue;
// 4. 排除仅含引号符号的无效情况(修复:只匹配替换后的符号)
var onlyQuote = Regex.IsMatch(cleanedText, @"^\s*[""']{1,2}\s*$");
// 规则A:包含典型对话结尾标点
bool endsWithDialogPunct = Regex.IsMatch(content, @"[。!??!…\.~~、,,]$");
// 规则B:长度至少4个字符(或按中文字数算)
bool isLongEnough = content.Length >= 4;
// 最终判断
return (hasQuote || hasSingleQuote) && !onlyQuote;
if (endsWithDialogPunct || isLongEnough)
{
hasValidDialogue = true;
break;
}
}
// 3. 单引号内容同理(可省略或同逻辑)
// 最终:有说话标记 或 存在有效对话内容,且不是“仅由引号符号组成”
bool onlyQuote = Regex.IsMatch(cleanedText, @"^\s*[""']{1,2}\s*$");
return (hasDialogueTag || hasValidDialogue) && !onlyQuote;
}
}
}