如何从正则表达式替换中获取每个单独的替换结果?
如何从正则表达式替换中获取每个单独的替换结果?
核心问题
我们可以用matcher.group()获取当前正则匹配到的内容,但有没有类似方法能直接拿到当前替换后的结果字符串?
Java 实现方案
Java标准库的Matcher类并没有直接提供获取单次替换结果的API,但可以通过以下几种可靠的变通方式实现:
方法1:记录StringBuilder长度差(最简便可靠)
在调用appendReplacement前后分别记录StringBuilder的长度,差值部分就是本次替换的结果:
public class Test { public static void main(String[] args) { String content_SearchOn = "Sample sentence: snake, snail, snow, spider"; String regexStrSubstitution = "$2$3$1"; String regexStrMatchFor = "(s)(.)(.)"; Matcher matcher = Pattern.compile(regexStrMatchFor).matcher(content_SearchOn); ArrayList<String> arr_regexMatchedWord = new ArrayList<>(); ArrayList<String> arr_regexMatchedSubstitution = new ArrayList<>(); StringBuilder sb_content_Replaced = new StringBuilder(); while (matcher.find()) { String regexMatchedWord = matcher.group(); arr_regexMatchedWord.add(regexMatchedWord); int beforeLength = sb_content_Replaced.length(); matcher.appendReplacement(sb_content_Replaced, regexStrSubstitution); int afterLength = sb_content_Replaced.length(); // 截取新增的替换内容 String regexMatchedSubstitution = sb_content_Replaced.substring(beforeLength, afterLength); arr_regexMatchedSubstitution.add(regexMatchedSubstitution); } matcher.appendTail(sb_content_Replaced); System.out.println(sb_content_Replaced); // Sample enstence: naske, nasil, nosw, pisder System.out.println(arr_regexMatchedWord); // [sen, sna, sna, sno, spi] System.out.println(arr_regexMatchedSubstitution); // [ens, nas, nas, nos, pis] } }
方法2:手动解析替换模板(需处理转义)
将替换模板中的$n替换为对应的matcher.group(n),注意处理转义字符(比如\$表示字面量$):
private static String getReplacementResult(Matcher matcher, String replacement) { StringBuilder result = new StringBuilder(); int i = 0; int len = replacement.length(); while (i < len) { char c = replacement.charAt(i); if (c == '\\') { // 处理转义字符,直接追加下一个字符 if (i + 1 < len) { result.append(replacement.charAt(i + 1)); i += 2; } else { // 末尾的转义符,直接追加 result.append(c); i++; } } else if (c == '$') { // 处理分组引用 if (i + 1 < len && Character.isDigit(replacement.charAt(i + 1))) { int groupNum = Character.getNumericValue(replacement.charAt(i + 1)); result.append(matcher.group(groupNum)); i += 2; } else { // 字面量$,直接追加 result.append(c); i++; } } else { result.append(c); i++; } } return result.toString(); }
调用时直接在find()后使用:
String regexMatchedSubstitution = getReplacementResult(matcher, regexStrSubstitution); arr_regexMatchedSubstitution.add(regexMatchedSubstitution);
方法3:反射(不推荐,依赖内部实现)
通过反射调用Matcher的私有方法appendExpandedReplacement来生成替换结果,但这种方法依赖JDK内部实现,版本更新可能导致失效:
import java.lang.reflect.Method; private static String getReplacementViaReflection(Matcher matcher, String replacement) throws Exception { StringBuilder result = new StringBuilder(); Method method = Matcher.class.getDeclaredMethod("appendExpandedReplacement", String.class, StringBuilder.class); method.setAccessible(true); method.invoke(matcher, replacement, result); return result.toString(); }
其他语言实现
JavaScript
JavaScript的replace方法支持传入函数作为替换器,函数的返回值就是本次替换结果,可以直接捕获:
const content = "Sample sentence: snake, snail, snow, spider"; const regex = /(s)(.)(.)/g; const matchedWords = []; const replacementResults = []; const replacedContent = content.replace(regex, (match, p1, p2, p3) => { matchedWords.push(match); // 生成替换结果 const replacement = p2 + p3 + p1; replacementResults.push(replacement); return replacement; }); console.log(replacedContent); // Sample enstence: naske, nasil, nosw, pisder console.log(matchedWords); // ["sen", "sna", "sna", "sno", "spi"] console.log(replacementResults); // ["ens", "nas", "nas", "nos", "pis"]
Python
Python的re.sub方法支持回调函数,函数接收匹配对象,返回替换内容,同时可以记录替换结果:
import re content = "Sample sentence: snake, snail, snow, spider" pattern = r"(s)(.)(.)" matched_words = [] replacement_results = [] def replace_callback(match): matched_words.append(match.group()) # 生成替换结果 replacement = match.group(2) + match.group(3) + match.group(1) replacement_results.append(replacement) return replacement replaced_content = re.sub(pattern, replace_callback, content) print(replaced_content) # Sample enstence: naske, nasil, nosw, pisder print(matched_words) # ['sen', 'sna', 'sna', 'sno', 'spi'] print(replacement_results) # ['ens', 'nas', 'nas', 'nos', 'pis']
内容的提问来源于stack exchange,提问作者Nor.Z
相关产品推荐
相关产品推荐

