From 445e3e2ad5547e4acbeab70249b33cc27028379b Mon Sep 17 00:00:00 2001
From: yuejiajun <1530620364@qq.com>
Date: Sun, 28 Sep 2025 13:16:25 +0800
Subject: [PATCH] =?UTF-8?q?=E7=BB=9F=E8=AE=A1=E8=A7=84=E5=88=99=E7=94=9F?=
=?UTF-8?q?=E6=95=88=E4=B8=8E=E6=9C=AA=E7=94=9F=E6=95=88?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../demo/draft/demo043/util/FormatUtil.java | 221 +++++++++++++++++-
1 file changed, 210 insertions(+), 11 deletions(-)
diff --git a/src/main/java/com/example/demo/draft/demo043/util/FormatUtil.java b/src/main/java/com/example/demo/draft/demo043/util/FormatUtil.java
index 186bdb3..cc8b2a6 100644
--- a/src/main/java/com/example/demo/draft/demo043/util/FormatUtil.java
+++ b/src/main/java/com/example/demo/draft/demo043/util/FormatUtil.java
@@ -7,6 +7,8 @@ import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Matcher;
@@ -1388,8 +1390,8 @@ public class FormatUtil {
*
支持正则表达式替换和普通字符串替换
* 可配置大小写敏感匹配
* 支持整词匹配(word boundary)
- * 提供正则表达式错误降级处理
- * 支持批量替换操作
+ * 提供详细的替换统计信息
+ * 记录未生效的替换规则
*
*
* @param source 源字符串,如果为null则直接返回null
@@ -1402,7 +1404,7 @@ public class FormatUtil {
* @param useRegex 是否使用正则表达式
* true: 将key作为正则表达式处理,false: 作为普通字符串处理
* @return 替换后的字符串,如果源字符串或替换映射表为null/空则返回原字符串
- * @throws IllegalArgumentException 当replacementMap包含null键或值时抛出
+ * @throws IllegalArgumentException 当replacementMap包含null键时抛出
*/
public static String stealBeamsAndReplacePillars(String source, Map replacementMap,
boolean caseSensitive, boolean wholeWord, boolean useRegex) {
@@ -1432,41 +1434,238 @@ public class FormatUtil {
String result = source;
int totalReplacements = 0;
+ List ineffectiveRules = new ArrayList<>(); // 记录未生效的规则
+ Map replacementStats = new HashMap<>(); // 记录每个规则的替换次数
+
+ // 计算源字符串的SHA1,用于精确比较变化
+ String sourceHash = calculateSHA1(source);
+ String currentResult = source;
+ String currentHash = sourceHash;
// 遍历替换映射表,按顺序应用每个替换规则
for (Map.Entry entry : replacementMap.entrySet()) {
String patternStr = entry.getKey();
String replacement = entry.getValue() != null ? entry.getValue() : "";
+ String previousHash = currentHash; // 记录应用规则前的hash
+
try {
if (useRegex) {
// 使用正则表达式替换
- log.info("应用替换规则(正则表达式替换): '{}' -> '{}'", patternStr, replacement);
- result = applyRegexReplacement(result, patternStr, replacement, caseSensitive, wholeWord);
+ log.debug("应用替换规则(正则表达式替换): '{}' -> '{}'", patternStr, replacement);
+ result = applyRegexReplacement(result, patternStr, replacement, caseSensitive, wholeWord, replacementStats);
} else {
// 使用普通字符串替换
- log.info("应用替换规则(普通字符串替换): '{}' -> '{}'", patternStr, replacement);
- result = applyLiteralReplacement(result, patternStr, replacement, caseSensitive, wholeWord);
+ log.debug("应用替换规则(普通字符串替换): '{}' -> '{}'", patternStr, replacement);
+ result = applyLiteralReplacement(result, patternStr, replacement, caseSensitive, wholeWord, replacementStats);
}
- // 统计替换次数(通过比较字符串长度变化估算)
- if (!result.equals(source)) {
+ // 计算当前结果的hash值
+ currentResult = result;
+ currentHash = calculateSHA1(currentResult);
+
+ // 统计替换次数:通过SHA1比较判断是否发生变化
+ boolean hasChanged = !currentHash.equals(previousHash);
+ int ruleReplacementCount = replacementStats.getOrDefault(patternStr, 0);
+
+ if (hasChanged && ruleReplacementCount > 0) {
totalReplacements++;
+ log.info("规则 '{}' 生效,替换次数: {}", patternStr, ruleReplacementCount);
+ } else {
+ // 记录未生效的规则
+ ineffectiveRules.add(patternStr);
+ log.info("规则 '{}' 未生效,未找到匹配项", patternStr);
}
} catch (Exception e) {
log.error("替换规则处理失败 - 模式: '{}', 替换值: '{}', 错误: {}",
patternStr, replacement, e.getMessage());
+ // 发生错误时,该规则视为未生效
+ ineffectiveRules.add(patternStr);
// 发生错误时继续处理下一个规则,不中断整个流程
}
}
- log.info("字符串替换完成,总应用规则数: {}, 实际产生变化的规则数: {}",
- replacementMap.size(), totalReplacements);
+ // 输出详细的统计信息
+ log.info("字符串替换完成,总应用规则数: {}, 实际产生变化的规则数: {}, 总替换次数: {}",
+ replacementMap.size(), totalReplacements, calculateTotalReplacements(replacementStats));
+
+ // 输出未生效的规则(DEBUG级别)
+ if (!ineffectiveRules.isEmpty() && log.isDebugEnabled()) {
+ log.info("以下 {} 个规则未生效: {}", ineffectiveRules.size(), ineffectiveRules);
+ }
+
+ // 输出每个规则的详细替换统计(DEBUG级别)
+ if (log.isDebugEnabled()) {
+ log.info("详细替换统计:");
+ for (Map.Entry stat : replacementStats.entrySet()) {
+ String rule = stat.getKey();
+ int count = stat.getValue();
+ String status = count > 0 ? "生效" : "未生效";
+ log.info("规则 '{}': {}次替换 - {}", rule, count, status);
+ }
+ }
return result;
}
+ /**
+ * 计算字符串的SHA1哈希值
+ *
+ * @param input 输入字符串
+ * @return SHA1哈希值,如果输入为null则返回空字符串
+ */
+ private static String calculateSHA1(String input) {
+ if (input == null) {
+ return "";
+ }
+ try {
+ MessageDigest digest = MessageDigest.getInstance("SHA-1");
+ byte[] hash = digest.digest(input.getBytes(StandardCharsets.UTF_8));
+ StringBuilder hexString = new StringBuilder();
+ for (byte b : hash) {
+ String hex = Integer.toHexString(0xff & b);
+ if (hex.length() == 1) hexString.append('0');
+ hexString.append(hex);
+ }
+ return hexString.toString();
+ } catch (NoSuchAlgorithmException e) {
+ log.warn("SHA1算法不可用,使用简单hash替代", e);
+ // 降级方案:使用简单的hashCode
+ return Integer.toHexString(input.hashCode());
+ }
+ }
+
+ /**
+ * 应用正则表达式替换,并统计替换次数
+ */
+ private static String applyRegexReplacement(String source, String regex, String replacement,
+ boolean caseSensitive, boolean wholeWord,
+ Map stats) {
+ String processedRegex = regex;
+
+ // 处理整词匹配
+ if (wholeWord && !processedRegex.startsWith("\\b") && !processedRegex.contains("\\b")) {
+ processedRegex = "\\b" + processedRegex + "\\b";
+ log.trace("添加单词边界,处理后的正则: {}", processedRegex);
+ }
+
+ try {
+ int flags = caseSensitive ? 0 : Pattern.CASE_INSENSITIVE;
+ Pattern pattern = Pattern.compile(processedRegex, flags);
+ Matcher matcher = pattern.matcher(source);
+
+ // 先统计匹配次数
+ int count = 0;
+ while (matcher.find()) {
+ count++;
+ }
+
+ // 记录统计信息
+ stats.put(regex, count);
+
+ // 执行替换
+ if (count > 0) {
+ matcher.reset();
+ return matcher.replaceAll(replacement);
+ } else {
+ return source; // 无匹配,返回原字符串
+ }
+
+ } catch (Exception e) {
+ log.warn("正则表达式编译或执行失败,降级为普通字符串替换 - 模式: '{}', 错误: {}",
+ regex, e.getMessage());
+ // 降级处理:使用普通字符串替换
+ return applyLiteralReplacement(source, regex, replacement, caseSensitive, wholeWord, stats);
+ }
+ }
+
+ /**
+ * 应用普通字符串替换,并统计替换次数
+ */
+ private static String applyLiteralReplacement(String source, String literal, String replacement,
+ boolean caseSensitive, boolean wholeWord,
+ Map stats) {
+ if (wholeWord) {
+ // 整词匹配处理:使用正则表达式实现单词边界匹配
+ try {
+ String regex = "\\b" + Pattern.quote(literal) + "\\b";
+ int flags = caseSensitive ? 0 : Pattern.CASE_INSENSITIVE;
+ Pattern pattern = Pattern.compile(regex, flags);
+ Matcher matcher = pattern.matcher(source);
+
+ // 统计匹配次数
+ int count = 0;
+ while (matcher.find()) {
+ count++;
+ }
+
+ // 记录统计信息
+ stats.put(literal, count);
+
+ // 执行替换
+ if (count > 0) {
+ matcher.reset();
+ return matcher.replaceAll(replacement);
+ } else {
+ return source; // 无匹配,返回原字符串
+ }
+ } catch (Exception e) {
+ log.warn("整词匹配处理失败,使用普通替换 - 模式: '{}'", literal);
+ // 降级为普通替换
+ }
+ }
+
+ // 普通字符串替换
+ int count;
+ String result;
+
+ if (caseSensitive) {
+ // 大小写敏感替换
+ result = source.replace(literal, replacement);
+ // 计算替换次数(通过字符串分割方式)
+ count = (source.length() - result.length()) / (literal.length() - replacement.length());
+ if (count < 0) count = 0; // 处理除数为0的情况
+ } else {
+ // 大小写不敏感替换
+ result = replaceIgnoreCase(source, literal, replacement);
+ count = countIgnoreCaseOccurrences(source, literal);
+ }
+
+ // 记录统计信息
+ stats.put(literal, count);
+
+ return result;
+ }
+
+ /**
+ * 计算字符串中不区分大小写的出现次数
+ */
+ private static int countIgnoreCaseOccurrences(String source, String target) {
+ if (source == null || target == null || target.isEmpty()) {
+ return 0;
+ }
+
+ int count = 0;
+ String lowerSource = source.toLowerCase();
+ String lowerTarget = target.toLowerCase();
+ int index = 0;
+
+ while ((index = lowerSource.indexOf(lowerTarget, index)) != -1) {
+ count++;
+ index += target.length();
+ }
+
+ return count;
+ }
+
+ /**
+ * 计算总替换次数
+ */
+ private static int calculateTotalReplacements(Map stats) {
+ return stats.values().stream().mapToInt(Integer::intValue).sum();
+ }
+
/**
* 应用正则表达式替换
*