相信平时在工作或学习中需要处理大量正则表达式的同志们对 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 文件进行测试,如果能够成功运行,说明你的 re2 已经能够成功在 C++ 中使用了,然后你便可以探索该模块了。


#include <re2/re2.h>
#include <stdio.h>
 
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 = repile(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 = "mike@axiak",
    url = "http://github/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]: []


配置过程中可能会出现一些问题,欢迎讨论。


更多推荐

Windows 下正则表达式库 re2 在 C++ 和 Python 中的编译和使用