在Python中,可以使用re.findall(pattern, string)来返回字符串中所有不重叠的模式匹配结果。例如,在下面的SVG路径命令中:
import re
spam = "M317.0,169.7C311.1,170.5 285.7,146.8 300.7,178.57 L 321.4,175.01"
eggs = re.findall("([A-Za-z]|-?[0-9]+.?[0-9]*(?:e-?[0-9]*)?)", spam)
print(eggs)
# 输出:['M', '317.0', '169.7', 'C', '311.1', '170.5', '285.7', '146.8', '300.7', '178.5', 'L', '321.4', '175.0']
然而,在C或C++中,有没有一种轻量级、简洁高效的方法来进行这种类型的正则表达式模式匹配呢?需要注意的是,这里不希望使用依赖于Boost的解决方案。理想情况下,希望最小化依赖项并保持代码精简。
2、解决方案
方法一:使用SLRE库
SLRE是一个ANSI C库,实现了一小部分Perl正则表达式。它主要针对那些想要解析配置文件并且速度无关紧要的开发人员。它只有一个.c文件,很容易根据自己的需求进行修改。例如,如果想要引入一个新的元字符'\i',表示'IP地址',就可以轻松地做到。
SLRE的特点:
- 跨平台 - 纯ANSI C
- 非常简单的API
- 轻量级:编译后大约5kB的代码
- 不使用动态内存分配
- 线程安全
SLRE支持的正则表达式语法: ^ 匹配缓冲区的开头 $ 匹配缓冲区的末尾 () 分组和子字符串捕获 [...] 匹配集合中的任何字符 [^...] 匹配除集合中的字符之外的任何字符 \s 匹配空白字符 \S 匹配非空白字符 \d 匹配十进制数字 \r 匹配回车 \n 匹配换行
-
匹配一次或多次(贪婪)
+? 匹配一次或多次(非贪婪)
-
匹配零次或多次(贪婪)
? 匹配零次或多次(非贪婪) ? 匹配零次或一次 \xDD 匹配具有十六进制值0xDD的字节 \meta 匹配元字符之一:^$().[+?\
方法二:使用C++正则表达式库
C++没有原生的(或STL)正则表达式支持,因此需要一个C++正则表达式库。有许多这样的库,但它们会创建依赖项。
使用C++正则表达式库的好处:
- 丰富且强大的正则表达式支持
- 可以很容易地创建复杂和嵌套的正则表达式
- 性能优化
使用C++正则表达式库的缺点:
- 需要创建一个依赖项
- 库的API可能不同
- 库的实现可能会有细微的差异
代码示例
在SLRE中,可以如下使用正则表达式进行匹配:
#include <slre.h>
#include <stdio.h>
int main() {
char *pattern = "([A-Za-z]|-?[0-9]+\.?[0-9]*(?:e-?[0-9]*)?)";
char *string = "M317.0,169.7C311.1,170.5 285.7,146.8 300.7,178.57 L 321.4,175.01";
slre_compile(pattern);
slre_match();
int n = slre_nsubpatterns();
for (int i = 0; i < n; i++) {
printf("%s\n", slre_get_string(i));
}
return 0;
}
在C++中,可以使用Boost.Regex库进行正则表达式匹配:
#include <boost/regex.hpp>
#include <iostream>
int main() {
std::string pattern = "([A-Za-z]|-?[0-9]+\.?[0-9]*(?:e-?[0-9]*)?)";
std::string string = "M317.0,169.7C311.1,170.5 285.7,146.8 300.7,178.57 L 321.4,175.01";
boost::regex re(pattern);
boost::sregex_iterator it(string.begin(), string.end(), re);
boost::sregex_iterator end;
while (it != end) {
std::cout << it->str() << std::endl;
++it;
}
return 0;
}