Windows 下正則表達式庫 re2 在 C++ 和 Python 中的編譯和使用

相信平時在工作或學習中需要處理大量正則表達式的同志們對 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 <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 = 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]: []


配置過程中可能會出現一些問題,歡迎討論。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章