Dart/Flutter中如何将字符串转为原始字符串用于正则匹配?
正则字符串转义与RegExp实例化问题
场景说明
我有一个正则表达式模式需要存储为String变量,模式内容如下:
(?<timestamp>\d+\/\d+\/\d+\s\d+:\d+:\d+\.\d+)\s(?<filename>[a-z]+\.[a-z]+:\d+):\s\[(?<type>[A-Z]+)\]:(?<text>[\s\S]+)
需要匹配的日志示例:
2060/12/12 12:12:12.017602 abc.go:000: [INFO]:abc.cpp:00:Parsing String : 1920x1080'
可行的写法
使用原始字符串或手动转义的普通字符串,都能成功匹配:
// 原始字符串写法:无需转义,直接写正则 String raw = r'(?<timestamp>\d+\/\d+\/\d+\s\d+:\d+:\d+\.\d+)\s(?<filename>[a-z]+\.[a-z]+:\d+):\s\[(?<type>[A-Z]+)\]:(?<text>[\s\S]+)'; // 普通字符串写法:每个\都要转义成\\ String non_raw = "(?<timestamp>\\d+\\/\\d+\\/\\d+\\s\\d+:\\d+:\\d+\\.\\d+)\\s(?<filename>[a-z]+\\.[a-z]+:\\d+):\\s\\[(?<type>[A-Z]+)\\]:(?<text>[\\s\\S]+)";
失败的尝试
我尝试用以下方法自动转义,但没有效果:
String convert2NonRaw(String pattern) { return pattern.replaceAll(r'\', r'\\'); }
解决方法
1. 代码中定义正则字符串
如果是在代码里直接定义这个正则模式,优先用原始字符串(r''),这是最简洁且不易出错的方式,不需要任何转义处理,直接把正则内容填进去就行。
如果必须用普通字符串,就得手动把每个\换成\\——因为普通字符串里\是转义符,只有写成\\才会被解析成单个\,供正则使用。
2. 外部获取正则字符串
如果这个正则字符串是从配置文件、数据库或接口等外部来源获取的,那它本身已经包含正确的正则符号(比如\d里的\),不需要额外转义,直接传给RegExp构造函数即可:
// 假设externalPattern是从外部获取的正则字符串 String externalPattern = "(?<timestamp>\\d+\\/\\d+\\/\\d+\\s\\d+:\\d+:\\d+\\.\\d+)\\s(?<filename>[a-z]+\\.[a-z]+:\\d+):\\s\\[(?<type>[A-Z]+)\\]:(?<text>[\\s\\S]+)"; RegExp exp = RegExp(externalPattern);
3. 为什么你的转换方法无效
你写的convert2NonRaw方法没用,是因为如果传入的pattern是用普通字符串定义的,那里面的\会被当作转义符处理——比如你写"\d",Dart会认为这是无效的转义序列,直接编译报错;就算是有效的转义(比如\s),实际存储的字符串里也没有\,而是对应的空白字符,所以replaceAll找不到要替换的\,自然没效果。
工具包说明
Dart本身不需要额外工具包来处理这个问题,只要按照上述规则正确处理字符串转义即可。
内容的提问来源于stack exchange,提问作者Utkarsh Gupta
相关产品推荐
相关产品推荐

