如何在Dart中使用正则表达式分组特定结构的数据块?
在Dart中用正则拆分RDF授权数据块
问题背景
输入的RDF文本如下:
@prefix : <#>. @prefix acl: <http://www.w3.org/ns/auth/acl#>. @prefix c: </profile/card#>. @prefix c0: <https://anushka.net/profile/card#>. @prefix c1: <https://isuru.net/profile/card#>. :ControlReadWrite a acl:Authorization; acl:accessTo <personal-data.ttl>; acl:agent c:me; acl:mode acl:Control, acl:Read, acl:Write. :ReadWrite a acl:Authorization; acl:accessTo <profile-data.ttl>; acl:agent c:me, c0:me; acl:mode acl:Read. :Read a acl:Authorization; acl:accessTo <medical-data.ttl>, <education-data.ttl>; acl:agent c:me, c0:me, c1:me; acl:mode acl:Read.
需求:忽略所有包含@prefix的行,将剩余内容拆分为3个独立的数据块,每个块是从 a acl:Authorization;开始到. 结尾的部分。
之前尝试的正则/a acl:Authorization([a-zA-Z;<>\n: -0-9]\.\n)/未生效,需要修正。
解决方案
问题分析
之前的正则存在几个关键问题:
- 字符集内的
-位置错误,:和0之间的-会被解析为字符范围(空格到0),而非单独的连字符; - 没有使用量词(如
+或*),仅匹配单个字符,无法覆盖跨行的内容; - 默认情况下
.不匹配换行符,导致无法跨行匹配完整数据块。
正确实现步骤
- 先过滤掉所有
@prefix行,简化匹配目标; - 使用支持跨行匹配的正则,精准捕获每个数据块。
Dart代码示例
void main() { final input = '''@prefix : <#>. @prefix acl: <http://www.w3.org/ns/auth/acl#>. @prefix c: </profile/card#>. @prefix c0: <https://anushka.net/profile/card#>. @prefix c1: <https://isuru.net/profile/card#>. :ControlReadWrite a acl:Authorization; acl:accessTo <personal-data.ttl>; acl:agent c:me; acl:mode acl:Control, acl:Read, acl:Write. :ReadWrite a acl:Authorization; acl:accessTo <profile-data.ttl>; acl:agent c:me, c0:me; acl:mode acl:Read. :Read a acl:Authorization; acl:accessTo <medical-data.ttl>, <education-data.ttl>; acl:agent c:me, c0:me, c1:me; acl:mode acl:Read.'''; // 过滤掉@prefix行 final filteredContent = input.split('\n') .where((line) => !line.trim().startsWith('@prefix')) .join('\n'); // 正则匹配目标数据块:开启dotAll让.匹配换行,非贪婪匹配到结尾的. final blockRegex = RegExp( r' a acl:Authorization;.*?\.(?=\n|$)', dotAll: true, ); // 提取所有匹配的块 final blocks = blockRegex.allMatches(filteredContent) .map((match) => match.group(0)) .whereType<String>() .toList(); // 输出结果 for (int i = 0; i < blocks.length; i++) { print('=== 第${i+1}个数据块 ==='); print(blocks[i]); } }
正则说明
dotAll: true:使.匹配包括换行在内的所有字符,支持跨行匹配;.*?:非贪婪匹配,确保匹配到最近的.(数据块结尾),避免过度匹配;(?=\n|$):正向预查,确认.后是换行符或字符串结束,保证每个块的完整性。
内容的提问来源于stack exchange,提问作者AnuIzu
相关产品推荐
相关产品推荐

