2011年5月15日 星期日

[C] C 語言,使用 Perl Compatible Regular Expressions (PCRE)

幾年前也寫過一篇:[C] C 語言,使用 Regular Expressions,那時是使用 Regex library 也曾說過要用看看 PCRE 啦,結果日子久了就都忘光光,倒是前陣子在 visual studio 編譯 c++ project 時,發現怎都忘光光 Orz 所以來寫一篇筆記吧。


至於 PCRE 的好處嘛,如果常開發 PHP 並使用 preg_match 或 preg_match_all 等相關函式庫的話,那使用的語法一致的啦。


簡單的 main.c 範例:


#include <pcre.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
int main( int argc, char ** argv)
{
        pcre *re;
        const char *error;
        int erroffset;
        int ovector[30];
        int options = 0;

        if( argc < 3 )
        {
                printf("Usage> %s \"PCRE_PATTERN\" \"TEST_DATA\"\n", argv[0]);
                return 0;
        }
        if( ( re = pcre_compile( argv[1], options, &error, &erroffset, NULL) ) == NULL )
        {
                fprintf(stderr, "PCRE compilation failed at offset %d: %s\n", erroffset, error);
                exit(1);
        }
        if( pcre_exec(re, NULL, argv[2], strlen(argv[2]), 0, 0, ovector, 30) >= 0 )
                printf("Match\n");
        else   
                printf("Not Found\n");
        return 0;
}


在 FreeBSD 編譯:


如果系統已經安裝過 pcre 相關 lib 的話,僅需編譯程式時,指定函式庫相關資訊即可


> gcc -I/usr/local/include -L/usr/local/lib -lpcre main.c


如果沒有安裝過,那只好去 PCRE - Perl Compatible Regular Expressions 官方網站下載原始碼來編譯一下。


> cd pcre_test
pcre_test> wget ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/pcre-8.12.tar.gz
pcre_test> tar -xvf pcre-8.12.tar.gz && cd pcre-8.12
pcre_test/pcre-8.12> cd pcre-8.12
pcre_test/pcre-8.12> ./configure && make && cd ..
pcre_test> ls
main.c          pcre-8.12/        pcre-8.12.tar.gz


pcre_test> gcc -DHAVE_CONFIG_H -DPCRE_STATIC -Ipcre-8.12 pcre-8.12/pcre_chartables.c pcre-8.12/pcre_compile.c pcre-8.12/pcre_config.c pcre-8.12/pcre_dfa_exec.c pcre-8.12/pcre_exec.c pcre-8.12/pcre_fullinfo.c pcre-8.12/pcre_get.c pcre-8.12/pcre_globals.c pcre-8.12/pcre_info.c pcre-8.12/pcre_maketables.c pcre-8.12/pcre_newline.c pcre-8.12/pcre_ord2utf8.c pcre-8.12/pcre_refcount.c pcre-8.12/pcre_study.c pcre-8.12/pcre_tables.c pcre-8.12/pcre_try_flipped.c pcre-8.12/pcre_ucd.c pcre-8.12/pcre_valid_utf8.c pcre-8.12/pcre_xclass.c pcre-8.12/pcre_version.c pcre-8.12/pcreposix.c main.c



pcre_test> gcc -Ipcre-8.12 main.c pcre-8.12/.libs/libpcre.a


pcre_test> ls
a.out*            main.c          pcre-8.12/        pcre-8.12.tar.gz


測試:


pcre_test> ./a.out 
Usage> ./a.out "PCRE_PATTERN" "TEST_DATA"
pcre_test> ./a.out "<a></a>" "<a>test</a>"
Not Found
pcre_test> ./a.out "<a>(.*?)</a>" "<a></a>"
Match


在 VC++ 編譯:


PCRE 內附 cmake 編譯方式,正統的方式應該是透過 cmake 編譯出 lib 來使用,在這邊就手動調調,直接用 src 把玩一下。


建立 2 個 projects,其中一個是 libpcre 另一個則是 main,前者是 PCRE 的相關資料,後者是上述的 main.c 例子。對 libpcre 來說,先把壓縮檔內 config.h.generic、pcre.h.generic 和 pcre_chartables.c.dist,分別複製成一份 config.h、pcre.h 和 pcre_chartables.c。


source, header


接著設定兩個 projects 的 properties 等,對 libpcre 和 main 兩者來說:


[C/C++] -> [General] -> [Additional Include Directories] 加入 pcre-8.12 的目錄位置


[C/C++] -> [Code Generation] -> [Runtime Library] 設定為 Multi-threaded (/MT) ,理由是我要用 static 的,並且不想使用 DLL ,這樣才比較 portable 。


multi-threaded


對 libpcre 個別設定:


[General] -> [Configuration Type] 設定為 Static library (.lib)


[C/C++] -> [Preprocessor] -> [Preprocessor Definitions] 加 HAVE_CONFIG_H;PCRE_STATIC; 


對 main 個別設定:


[Common Properties] -> [Framework and References] -> [Add New Reference],請加入 libpcre


[C/C++] -> [Preprocessor] -> [Preprocessor Definitions] 加 PCRE_STATIC; 即可


[Project Dependencies],對 main Projects 請勾選 libpcre ,這樣編譯過程會先編 libpcre


dependencise


如此一來就能夠 build 出來啦


其他筆記:


如果編譯過程中會有 error LNK2001: unresolved external symbol __pcre_default_tables 的話,那應該是 libpcre 編譯過程中少了 pcre_chartables.c 檔案,可以從 pcre_chartables.c.dist 複製出來;若是 error LNK2019: unresolved external symbol __imp__pcre_exec referenced in function _main 這類的,那應該是 main project 之 preprocessor definitions 忘了加 PCRE_STATIC  或是 Framework and References 要加一下 libpcre 囉


沒有留言:

張貼留言