提高c++正则表达式替换性能
Increase C++ regex replace performance
我是一个c++编程初学者,在一个小型c++项目上工作,我必须处理许多相对较大的XML文件并从中删除XML标记。我使用c++ 0x正则表达式库成功地做到了这一点。但是,我遇到了一些性能问题。只是读取文件并在其内容上执行regex_replace函数在我的PC上大约需要6秒。我可以通过添加一些编译器优化标志将其减少到2。然而,使用Python,我可以在不到100毫秒的时间内完成。显然,我在c++代码中做了一些非常低效的事情。我怎么做才能加快速度呢?
我的c++代码:
std::regex xml_tags_regex("<[^>]*>");
for (std::vector<std::string>::iterator it = _files.begin(); it !=
_files.end(); it++) {
std::ifstream file(*it);
file.seekg(0, std::ios::end);
size_t size = file.tellg();
std::string buffer(size, ' ');
file.seekg(0);
file.read(&buffer[0], size);
buffer = regex_replace(buffer, xml_tags_regex, "");
file.close();
}
My Python code:
regex = re.compile('<[^>]*>')
for filename in filenames:
with open(filename) as f:
content = f.read()
content = regex.sub('', content)
注:我真的不关心一次处理完整的文件。我只是发现一行一行、一个字一个字或一个字一个字地阅读文件会大大减慢速度。
c++ 11正则表达式替换确实相当慢,至少到目前为止是这样。PCRE在模式匹配速度方面表现得更好,然而,PCRECPP为基于正则表达式的替换提供了非常有限的方法,引用手册页:
你可以用"rewrite"替换"str"中"pattern"的第一个匹配。在"rewrite"中,反斜杠转义的数字(1到9)可用于中插入与圆括号组相匹配的文本模式。"rewrite"中的 是指整个匹配的文本。
与Perl的's'命令相比,这真的很糟糕。这就是为什么我围绕PCRE编写了自己的c++包装器,它以一种接近Perl's '的方式处理基于正则表达式的替换,并且还支持16位和32位字符串:
命令字符串语法
命令语法遵循Perl
s/pattern/substitute/[options]
公约。任何字符(除了反斜杠)都可以用作分隔符,不仅仅是
/
,但要确保分隔符被转义为如果在pattern
,substitute
或options
中使用反斜杠()子字符串,例如:
s/\///g
将所有反斜杠替换为正斜杠记住在c++代码中使用双反斜杠,除非使用原始字符串文字(参见字符串文字):
pcrscpp::replace rx("s/\\/\//g");
模式字符串语法
模式字符串直接传递给
pcre*_compile
,因此必须按照PCRE文档中描述的PCRE语法。替换字符串语法
替代字符串反向引用语法类似于Perl的:
$1
…$n
:第n个捕获子模式匹配$&
和$0
:整个匹配${label}
:标记子模式匹配。label
最多为32个字母数字+下划线字符('A'-'Z'
,'a'-'z'
,'0'-'9'
,'_'
),第一个字符必须是字母$`
和$'
(反勾号和勾号)是指前面的主题区域和比赛结束后。在Perl中,未修改的也可以识别以下转义序列:
n
: newliner
:回车t
:水平标签f
: form feedb
: backspacea
: alarm, belle
: escape