Dart正则如何捕获指定~符号分组并忽略其他相似模式
问题原因
你当前使用的split正则~+、~~+、~~~+会匹配任意大于等于对应数量的连续序列,比如`~+`可以同时匹配1/2/3个连续,~~+可以同时匹配2/3个连续,会把其他长度的也作为拆分符,自然会出现不同分组内容混杂的问题。
解决方案
使用负向前后断言确保匹配的是恰好对应数量的连续,避免和更长的序列混淆,再配合简单的内容过滤即可得到预期结果,示例代码如下:
String f = '~the calculator is on and working~I entered 50 into the calculator' '~~I press add button~~holding equal button ~~~The result should be 50'; // 拆分规则:仅匹配前后无其他~的对应数量~序列 final singleTildeSplit = RegExp(r'(?<!~)~(?!~)'); final doubleTildeSplit = RegExp(r'(?<!~)~~(?!~)'); final tripleTildeSplit = RegExp(r'(?<!~)~~~(?!~)'); // 提取givens:拆分后去掉空值,截取到多~符号前的有效内容 List<String> givens = f.split(singleTildeSplit) .map((item) => item.split(RegExp(r'~{2,}')).first) .where((item) => item.trim().isNotEmpty) .toList(); // 提取whens:拆分后过滤掉包含其他数量~的无效内容 List<String> whens = f.split(doubleTildeSplit) .where((item) => !item.contains('~') && item.trim().isNotEmpty) .toList(); // 提取thens:拆分后过滤空值即可 List<String> thens = f.split(tripleTildeSplit) .where((item) => item.trim().isNotEmpty) .toList(); // 输出测试 print("givens结果:"); for (var ss in givens) { print(ss); } print('xxxxxxxxxxxx'); print("whens结果:"); for (var ss in whens) { print(ss); } print('xxxxxxxxxxxx'); print("thens结果:"); for (var ss in thens) { print(ss); }
运行后输出如下:
givens结果: the calculator is on and working I entered 50 into the calculator xxxxxxxxxxxx whens结果: I press add button xxxxxxxxxxxx thens结果: The result should be 50
完全符合预期的输出要求。
如果你的场景中是固定成对使用~内容~、~~内容~~、~~~内容~~~格式,也可以使用捕获组正则一次性完成分类提取,效率更高:
final matchExp = RegExp(r'(?<!~)(~{1,3})(.*?)(?<!~)\1(?!~)'); List<String> givens = []; List<String> whens = []; List<String> thens = []; // 匹配所有成对包裹的内容 matchExp.allMatches(f).forEach((match) { final tildeLen = match.group(1)!.length; final content = match.group(2)!; switch(tildeLen) { case 1: givens.add(content); break; case 2: whens.add(content); break; case 3: thens.add(content); break; } }); // 额外补充匹配单~包裹结束后到~~之间的非包裹内容 final firstDoubleTildeIndex = f.indexOf('~~'); final firstSingleTildeEndIndex = f.indexOf('~', 1); if (firstSingleTildeEndIndex > 0 && firstDoubleTildeIndex > firstSingleTildeEndIndex) { givens.add(f.substring(firstSingleTildeEndIndex + 1, firstDoubleTildeIndex).trim()); }
内容的提问来源于stack exchange,提问作者cattarantadoughan
相关产品推荐
相关产品推荐

