相信平时在工作或学习中需要处理大量正则表达式的同志们对 google 大名鼎鼎的 re2 模块一定不陌生,但之前在网上进行搜索时,很多人说无法在 windows 系统使用该模块。本文简述了 windows 系统下 re2 模块在 C++ 和 Python 中的使用。现以 64bit 为例,将其编译过程介绍如下,32bit 编译过程大同小异。
一、在 C++ 中的编译和使用:
1、其实对于 re2 模块而言,虽然 官方 所得到的包在 windows 下无法顺利编译,但其实早已经有人做了该模块的 windows 编译版本 re2win,可在 windows 下使用。
2、下载得到 re2-2011-09-30-src-win32.zip 后,可将该包中的所有文件解压至某一目录下,例如 D:\Library\re2\x64 ,如下图所示:
3、现在很简单了,用 vs 编译器打开工程文件 re2.vcproj , 由于我想要得到 64bit 版本的 re2 库,打开 vs 的 Configuration Manager 进行设置就可以了,设置完成后,右击工程名称 re2 , 在弹出的右键菜单中选择 build , 等待数十秒后,就发现编译完成了, 通过修改 Debug/Release 选项,同样可以生成不同的 lib 文件。
4、通过以上操作,如果同时编译了 Debug/Release 版,那么 D:\Library\re2\x64 文件夹大致会变成下图这样,其中 Debug 和 Release 文件夹分别包含了不同编译选项所得到的 re2.lib 文件。
5、测试 re2.lib 。新建一个 vc++ 工程 testre2 , 如下图修改项目属性,完成后可以对 testinstall.cc 文件进行测试,如果能够成功运行,说明你的 re2 已经能够成功在 C++ 中使用了,然后你便可以探索该模块了。
#include
#include
using namespace re2;
int main(void) {
if(RE2::FullMatch("axbyc", "a.*b.*c")) {
printf("PASS\n");
return 0;
}
printf("FAIL\n");
return 2;
}
二、在 Python 中的编译和使用:
关于 re2 在 Python 中的使用,这里需要注意的是网络上关于 python-re2 模块的 bug 问题。对于 re2 库 0.2.20 版本,不管是在 pypi 上的源码,还是二进制版本,都是存在 bug 的,具体的 bug 情况可以参考 链接1 ,链接2 和 链接3 。
所以如果想在 python 中正确使用 re2 的话,你应该自己去 github 上下载, pyre2 是一个经测试可以正确使用的包。但在对该包进行 python setup.py install 时,由于需要依赖上面所编译的 re2 的 C++ 版本,因此需要对一些文件进行修改, 具体如下。
1、解压该包后,打开 setup.py 文件,很明显可以发现该文件中会查找 C++ 版本 re2 的安装路径,且是完全基于 Linux 系统的,不符合咱们的要求,这里应该将该文件修改成下面这样,其中 re2_prefix 对应你自己的安装路径。
#!/usr/bin/env python
import sys
import os
import re
from distutils.core import setup, Extension, Command
class TestCommand(Command):
description = 'Run packaged tests'
user_options = []
def initialize_options(self):
pass
def finalize_options(self):
pass
def run(self):
from tests import re2_test
re2_test.testall()
cmdclass = {'test': TestCommand}
ext_files = []
if '--cython' in sys.argv[1:]:
# Using Cython
sys.argv.remove('--cython')
from Cython.Distutils import build_ext
cmdclass['build_ext'] = build_ext
ext_files.append("src/re2.pyx")
else:
# Building from C
ext_files.append("src/re2.cpp")
re2_prefix = "D:/Library/re2/x64"
BASE_DIR = os.path.dirname(__file__)
def get_long_description():
readme_f = open(os.path.join(BASE_DIR, "README.rst"))
readme = readme_f.read()
readme_f.close()
return readme
def get_authors():
author_re = re.compile(r'^\s*(.*?)\s+<.*?\@.*?>', re.M)
authors_f = open(os.path.join(BASE_DIR, "AUTHORS"))
authors = [match.group(1) for match in author_re.finditer(authors_f.read())]
authors_f.close()
return ', '.join(authors)
setup(
name="re2",
version="0.2.20",
description="Python wrapper for Google's RE2 using Cython",
long_description=get_long_description(),
author=get_authors(),
license="New BSD License",
author_email = "[email protected]",
url = "http://github.com/axiak/pyre2/",
ext_modules = [Extension("re2",
ext_files,
language="c++",
include_dirs=[re2_prefix],
libraries=["re2"],
library_dirs=[os.path.join(re2_prefix, "Release").replace('\\','/')],
runtime_library_dirs=[os.path.join(re2_prefix, "Release").replace('\\','/')],
)],
cmdclass=cmdclass,
classifiers = [
'License :: OSI Approved :: BSD License',
'Programming Language :: Cython',
'Programming Language :: Python :: 2.5',
'Programming Language :: Python :: 2.6',
'Intended Audience :: Developers',
'Topic :: Software Development :: Libraries :: Python Modules',
],
)
2、打开 cmd ,切换到 setup.py 所在的路径,执行命令 python setup.py install ,但或许会出现以下错误。
warning: I don't know what to do with 'runtime_library_dirs': ['D:/Library/re2/x64/Release']
error: don't know how to set runtime library search path for MSVC++
3、有两种修改该错误的方法,第一种是注释掉 setup.py 文件中 runtime_library_dirs 所在的那一行,另一种方法是修改文件 C:\Python27\Lib\distutils\msvc9compiler.py 中 755 行处的函数 runtime_library_dir_option ,使其返回值与 752 行的 library_dir_option 函数相同,而不是抛出这莫名其妙的异常,所作的修改具体如下:
def runtime_library_dir_option(self, dir):
return "/LIBPATH:" + dir
# raise DistutilsPlatformError(
# "don't know how to set runtime library search path for MSVC++")
4、不出意外的话,应该可以正确在 python 中使用 re2 模块了,测试如下:
In [1]: import re2
In [2]: import re
In [3]: re.search("((?:[01]?\d{1,2}|2[0-4]\d|25[0-5])\.){3}(?:[01]?\d{1,2}|2[0-4]\d|25[0-5])", "hello 28.224.2.1 test").group()
Out[3]: '28.224.2.1'
In [4]: re2.search("((?:[01]?\d{1,2}|2[0-4]\d|25[0-5])\.){3}(?:[01]?\d{1,2}|2[0-4]\d|25[0-5])", "hello 28.224.2.1 test").group()
Out[4]: '28.224.2.1'
In [5]: re.search("(\d{3})\D?(\d{3})\D?(\d{4})", "800-555-1212").groups()
Out[5]: ('800', '555', '1212')
In [6]: re2.search("(\d{3})\D?(\d{3})\D?(\d{4})", "800-555-1212").groups()
Out[6]: ('800', '555', '1212')
In [7]: re.findall(r'.', '\x80\x81\x82')
Out[7]: ['\x80', '\x81', '\x82']
In [8]: re2.findall(r'.', '\x80\x81\x82')
Out[8]: []
配置过程中可能会出现一些问题,欢迎讨论。