re2正則表達式匹配引擎的c接口版本cre2的中文使用手冊

前言

re2 官方地址:
https://github.com/google/re2

cre2 官方地址:
https://github.com/marcomaggi/cre2

1 基本類型定義

不透明類型:cre2_regexp_t 
  • 正則表達式對象的不透明類型; 它用於
    聲明指向對象的指針。此類型的實例可用於
    任意數量的匹配操作,並且對於
    多個線程併發使用是安全的。

Struct Typedef:cre2_string_t 
  • 用於引用另一個
    字符串的一部分的簡單數據結構。它有以下領域:
 'const char * data'
      Pointer to the first byte in the referenced substring.

 'int length'
      The number of bytes in the referenced substring.

Enumeration Typedef: cre2_error_code_t 
  • 返回的錯誤代碼的枚舉類型

2 函數使用

函數:cre2_regexp_t * cre2_new(const char * PATTERN,int 
PATTERN_LEN,const cre2_options_t * OPT)
  • 構建並返回一個新的正則表達式對象,表示
    PATTERN_LEN字節長度的PATTERN; 該對象配置了
    OPT中的選項。如果內存分配失敗:返回值
    是’NULL’指針。

void cre2_delete(cre2_regexp_t * REX)
  • 完成釋放所有相關
    資源的正則表達式對象。

const char * cre2_pattern(const cre2_regexp_t * REX)
  • REX是否是成功構建的正則表達式對象
    :返回指向模式字符串的指針。返回的指針
    僅在REX處於活動狀態時有效:如果’cre2_delete()'應用於
    REX,則指針變爲無效。

int cre2_num_capturing_groups(const cre2_regexp_t * REX)
  • 如果REX是一個成功構建的正則表達式對象:返回一個
    非負整數,表示模式中捕獲組的數量
    (括號子表達式)。如果
    在構建REX時發生錯誤:返回’-1’。

int cre2_find_named_capturing_groups(const cre2_regexp_t 
* REX,const char * NAME)
  • 如果REX是成功構建的正則表達式對象:返回一個
    非負整數,表示
    名稱爲NAME 的命名捕獲組的索引。如果在構建REX時發生錯誤
    或名稱無效:返回“-1”。

3 使用方法

      const char *      pattern = "from (?P<S>.*) to (?P<D>.*)";
      cre2_options_t *  opt     = cre2_opt_new();
      cre2_regexp_t *   rex     = cre2_new(pattern, strlen(pattern),
                                           opt);
      {
        if (cre2_error_code(rex))
          { /* handle the error */ }
        int nmatch = cre2_num_capturing_groups(rex) + 1;
        cre2_string_t strings[nmatch];
        int e, SIndex, DIndex;

        const char * text = \
           "from Montreal, Canada to Lausanne, Switzerland";
        int text_len = strlen(text);

        e = cre2_match(rex, text, text_len, 0, text_len,
                       CRE2_UNANCHORED, strings, nmatch);
        if (0 == e)
          { /* handle the error */ }

        SIndex = cre2_find_named_capturing_groups(rex, "S");
        if (0 != strncmp("Montreal, Canada",
                         strings[SIndex].data, strings[SIndex].length))
          { /* handle the error */ }

        DIndex = cre2_find_named_capturing_groups(rex, "D");
        if (0 != strncmp("Lausanne, Switzerland",
                         strings[DIndex].data, strings[DIndex].length))
          { /* handle the error */ }
      }
      cre2_delete(rex);
      cre2_opt_delete(opt);

int cre2_program_size(const cre2_regexp_t * REX)
  • 如果REX是一個成功構建的正則表達式對象:返回一個
    表示程序大小的非負整數,它
    是正則表達式“成本” 的非常近似的度量; 較大的數字比較
    小的數字更昂貴。如果在
    構建REX時發生錯誤:返回’-1’。

int cre2_error_code(const cre2_regexp_t * REX)
  • 如果在構建REX時發生錯誤:返回
    表示相關錯誤代碼的整數。如果沒有錯誤則返回零

const char * cre2_error_string(const cre2_regexp_t * REX)
  • 如果在構建REX時發生錯誤:返回指向
    表示相關錯誤消息的ASCIIZ字符串的指針。在
    返回的指針是唯一的,而REX是有效的:如果
    將"cre2_delete()"應用到REX指針變爲無效。

Demo

 If REX is a successfully built regular expression object: return a
 pointer to an empty string.

 The following code:

      cre2_regexp_t *   rex;

      rex = cre2_new("ci(ao", 5, NULL);
      {
        printf("error: code=%d, msg=\"%s\"\n",
               cre2_error_code(rex),
               cre2_error_string(rex));
      }
      cre2_delete(rex);

 prints:

      error: code=6, msg="missing ): ci(ao"
void cre2_error_arg(const cre2_regexp_t * REX,
cre2_string_t * ARG)
  • 如果在構建REX時發生錯誤:
    用表示模式的
    違規部分的字節間隔填充ARG引用的結構。

demo

 If REX is a successfully built regular expression object: ARG
 references an empty string.

 The following code:

      cre2_regexp_t *   rex;
      cre2_string_t     S;

      rex = cre2_new("ci(ao", 5, NULL);
      {
        cre2_error_arg(rex, &S);
        printf("arg: len=%d, data=\"%s\"\n", S.length, S.data);
      }
      cre2_delete(rex);

 prints:

      arg: len=5 data="ci(ao"

4匹配配置

 cre2_options_t *  opt;

 opt = cre2_opt_new();
 cre2_opt_set_log_errors(opt, 0);
Opaque Typedef:cre2_options_t 
  • 選項對象的不透明指針的類型。此
    類型的任何實例都可用於配置任意數量的正則表達式
    對象。

Enumeration Typedef:cre2_encoding_t 
  • 選擇編碼的常量的枚舉類型。它包含
      CRE2_UNKNOWN
      CRE2_UTF8
      CRE2_Latin1

 The value 'CRE2_UNKNOWN' should never be used: it exists only in
 case there is a mismatch between the definitions of RE2 and CRE2.

cre2_options_t * cre2_opt_new(void)
  • 分配並返回一個新的選項對象。如果內存分配
    失敗:返回值是’NULL’指針。

Function:void cre2_opt_delete(cre2_options_t * OPT)
  • 完成釋放所有相關資源的選項對象。
    與此對象中配置編譯的正則表達式不會
    受其破壞。

以下所有函數都是正則
表達式選項的getter和setter ; setter的FLAG參數必須爲false才能
禁用該選項,而true爲true以啓用它; 除非另行指定,否則
如果啓用該選項,則“int”返回值爲true,如果
禁用,則返回false 。

void cre2_opt_set_encoding(cre2_options_t * OPT,
cre2_encoding_t ENC)
  • 默認情況下,正則表達式模式和輸入文本被
    解釋爲UTF-8。CRE2_Latin1編碼使它們被
    解釋爲Latin-1。

int cre2_opt_posix_syntax(cre2_options_t * OPT)
void cre2_opt_set_posix_syntax(cre2_options_t * OPT,int 
FLAG)
  • void cre2_opt_set_posix_syntax(cre2_options_t * OPT,int
    FLAG)將regexp 限制爲POSIX egrep語法。默認是禁用的。

- 函數:int cre2_opt_longest_match(cre2_options_t * OPT)
- 功能:void cre2_opt_set_longest_match(cre2_options_t * OPT,int 
FLAG)
  • 搜索最長匹配,而不是第一次匹配。默認是禁用的。

- Function:int cre2_opt_log_errors(cre2_options_t * OPT)
- 功能:void cre2_opt_set_log_errors(cre2_options_t * OPT,int 
FLAG)

— 將語法和執行錯誤記錄到’stderr’。默認值已啓用。

Function:int cre2_opt_literal(cre2_options_t * OPT)
void cre2_opt_set_literal(cre2_options_t * OPT,int FLAG)
  • 將模式字符串解釋爲文字,而不是正則表達式。
    默認是禁用的。

demo

 Setting this option is equivalent to quoting all the special
 characters defining a regular expression pattern:

      cre2_regexp_t *   rex;
      cre2_options_t *  opt;
      const char *      pattern = "(ciao) (hello)";
      const char *      text    = pattern;
      int               len     = strlen(pattern);

      opt = cre2_opt_new();
      cre2_opt_set_literal(opt, 1);
      rex = cre2_new(pattern, len, opt);
      {
        /* successful match */
        cre2_match(rex, text, len, 0, len,
                   CRE2_UNANCHORED, NULL, 0);
      }
      cre2_delete(rex);
      cre2_opt_delete(opt);

Function:int cre2_opt_never_nl(cre2_options_t * OPT)
void cre2_opt_set_never_nl(cre2_options_t * OPT,int 
FLAG)
  • 永遠不要匹配換行符,即使它在正則
    表達式模式中也是如此; 默認爲禁用。啓用此選項
    允許我們針對
    多行文本的開頭嘗試部分匹配,而不使用子
    模式排除正則表達式模式中的換行符。

int cre2_opt_dot_nl(cre2_options_t * OPT)
void cre2_opt_set_dot_nl(cre2_options_t * OPT,int FLAG)
  • 點匹配所有內容,包括新行; 默認爲
    禁用。

Function:int cre2_opt_never_capture(cre2_options_t * OPT)
void cre2_opt_set_never_capture(cre2_options_t * OPT,int 
FLAG)
  • 所有括號解析爲非捕獲; 默認爲禁用。

Function:int cre2_opt_case_sensitive(cre2_options_t * OPT)
void cre2_opt_set_case_sensitive(cre2_options_t * OPT,
int FLAG)
  • 匹配區分大小寫; 正則表達式模式可以
    使用’(?i)覆蓋此設置,除非在POSIX語法
    模式下配置。默認值已啓用。

Function:int cre2_opt_max_mem(cre2_options_t * OPT)
void cre2_opt_set_max_mem(cre2_options_t * OPT,int M)
  • max memory選項控制可以使用多少內存來保存
    正則表達式及其緩存DFA
    圖的編譯形式。這些函數設置並獲得這樣的內存量。有關
    詳細信息,請參閱RE2的文檔。

  • 啓用POSIX語法時,僅查詢以下選項; 禁用POSIX語法時:這些功能始終處於
    啓用狀態且無法關閉。

啓用POSIX語法時,僅查詢以下選項; 禁用POSIX語法時:這些功能始終處於
啓用狀態且無法關閉。

Function:int cre2_opt_perl_classes(cre2_options_t * OPT)
void cre2_opt_set_perl_classes(cre2_options_t * OPT,int 
FLAG)
  • 允許Perl的’\ d’,’\ s’,’\ w’,’\ D’,’\ S’, ‘\ W’。默認爲
    禁用。

int cre2_opt_word_boundary(cre2_options_t * OPT)
void cre2_opt_set_word_boundary(cre2_options_t * OPT,int 
FLAG)
  • 允許Perl的’\ b’,’\ B’(字邊界而不是)。默認爲
    禁用。

int cre2_opt_one_line (cre2_options_t * OPT) 
void cre2_opt_set_one_line (cre2_options_t * OPT, int 
FLAG) 
  • 模式’^‘和’$'僅匹配文本的開頭和結尾。默認爲禁用。

5 匹配正則表達式

基本模式匹配如下:

 cre2_regexp_t *   rex;
 cre2_options_t *  opt;
 const char *      pattern = "(ciao) (hello)";

 opt = cre2_opt_new();
 cre2_opt_set_posix_syntax(opt, 1);

 rex = cre2_new(pattern, strlen(pattern), opt);
 {
   const char *   text     = "ciao hello";
   int            text_len = strlen(text);
   int            nmatch   = 3;
   cre2_string_t  match[nmatch];

   cre2_match(rex, text, text_len, 0, text_len, CRE2_UNANCHORED,
              match, nmatch);

   /* prints: full match: ciao hello */
   printf("full match: ");
   fwrite(match[0].data, match[0].length, 1, stdout);
   printf("\n");

   /* prints: first group: ciao */
   printf("first group: ");
   fwrite(match[1].data, match[1].length, 1, stdout);
   printf("\n");

   /* prints: second group: hello */
   printf("second group: ");
   fwrite(match[2].data, match[2].length, 1, stdout);
   printf("\n");
 }
 cre2_delete(rex);
 cre2_opt_delete(opt);
- Enumeration Typedef:cre2_anchor_t 

  • 匹配操作的錨點的枚舉類型。它
    包含以下常量:
      CRE2_UNANCHORED
      CRE2_ANCHOR_START
      CRE2_ANCHOR_BOTH

int cre2_match(const cre2_regexp_t * REX,const char * 
TEXT,int TEXT_LEN,int START_POS,int END_POS,cre2_anchor_t 
ANCHOR,cre2_string_t * MATCH,int NMATCH)
  • 匹配TEXT引用的文本的子字符串並保持
    TEXT_LEN字節對正則表達式對象REX。
    如果文本匹配則返回true,否則返回false。

 The zero-based indices START_POS (inclusive) and END_POS
 (exclusive) select the substring of TEXT to be examined.  ANCHOR
 selects the anchor point for the matching operation.

 Data about the matching groups is stored in the array MATCH, which
 must have at least NMATCH entries; the referenced substrings are
 portions of the TEXT buffer.  If we are only interested in
 verifying if the text matches or not (ignoring the matching
 portions of text): we can use 'NULL' as MATCH argument and 0 as
 NMATCH argument.

 The first element of MATCH (index 0) references the full portion of
 the substring of TEXT matching the pattern; the second element of
 MATCH (index 1) references the portion of text matching the first
 parenthetical subexpression, the third element of MATCH (index 2)
 references the portion of text matching the second parenthetical
 subexpression; and so on.

int cre2_easy_match(const char * PATTERN,int 
PATTERN_LEN,const char * TEXT,int TEXT_LEN,cre2_string_t * 
MATCH,int NMATCH)
  • 與’cre2_match()'類似,但模式被指定爲包含
    PATTERN_LEN字節的字符串PATTERN 。此外,文本完全匹配,無需
    錨定。
  • 如果文本匹配模式,返回值爲1,如果文本不匹配模式,返回值爲0,如果模式是不合法的,則返回值爲2

Struct Typedef:cre2_range_t 
  • 結構類型,用於表示要
    作爲起始和結束索引匹配的文本的子字符串。它有如下字段:
 'long start'
      Inclusive start byte index.

 'long past'
      Exclusive end byte index.
void cre2_strings_to_ranges(const char * TEXT,
cre2_range_t * RANGES,cre2_string_t * STRINGS,int NMATCH)
  • 給定一個STRINGS數組,其中NMATCH元素是將
    TEXT與正則表達式匹配的結果:
    用索引間隔填充RANGES 數組在TEXT緩衝區中表示
    相同的結果。

demo

    cre2_regexp_t *	rex;
    cre2_options_t *	opt;
    const char *		pattern;
    pattern = "(ciao) (hello)";
    opt = cre2_opt_new();
    rex = cre2_new(pattern, strlen(pattern), opt);
    {
      if (cre2_error_code(rex))
        printf("rex error \n");
      int			nmatch = 3;
      cre2_string_t	strings[nmatch];
      cre2_range_t	ranges[nmatch];
      int			e;
      const char *	text = "ciao hello";
      int			text_len = strlen(text);

      e = cre2_match(rex, text, text_len, 0, text_len, CRE2_UNANCHORED, strings, nmatch);
      if (1 != e)
        printf("match error \n");
      cre2_strings_to_ranges(text, ranges, strings, nmatch);
      printf("full match: ");
      printf("%.*s\n", ranges[0].past-ranges[0].start,text+ranges[0].start);
      printf("\n");
      printf("first group: ");
      printf("%.*s\n", ranges[1].past-ranges[1].start,text+ranges[1].start);
      printf("\n");
      printf("second group: ");
      printf("%.*s\n", ranges[2].past-ranges[2].start,text+ranges[2].start);
      printf("\n");
    }
    cre2_delete(rex);
    cre2_opt_delete(opt);

結果:

full match: ciao hello

first group: ciao

second group: hello

實例

以下示例是成功匹配:

 const char *   pattern = "ci.*ut";
 const char *   text    = "ciao salut";
 cre2_string_t  input   = {
   .data   = text,
   .length = strlen(text)
 };
 int            result;
 result = cre2_full_match(pattern, &input, NULL, 0);

 result => 1

以下示例是成功匹配,其中
忽略括號子表達式:

 const char *   pattern = "(ciao) salut";
 const char *   text    = "ciao salut";
 cre2_string_t  input   = {
   .data   = text,
   .length = strlen(text)
 };
 int            result;
 result = cre2_full_match(pattern, &input, NULL, 0);

 result => 1

以下示例是成功匹配,其中
報告了與括號子表達式匹配的文本部分:

 const char *   pattern = "(ciao) salut";
 const char *   text    = "ciao salut";
 cre2_string_t  input   = {
   .data   = text,
   .length = strlen(text)
 };
 int            nmatch  = 1;
 cre2_string_t  match[nmatch];
 int            result;
 result = cre2_full_match(pattern, &input, match, nmatch);

 result => 1
 strncmp(text, input.data, input.length)         => 0
 strncmp("ciao", match[0].data, match[0].length) => 0

1. int cre2_full_match(const char * PATTERN,const 
cre2_string_t * TEXT,cre2_string_t * MATCH,int NMATCH)
2. int cre2_full_match_re(cre2_regexp_t * REX,const 
cre2_string_t * TEXT,cre2_string_t * MATCH,int NMATCH)
  • 匹配零終止字符串PATTERN或
    針對完整緩衝區TEXT 的預編譯正則表達式REX。
 For example: the text 'abcdef' matches the pattern 'abcdef'
 according to this function, but neither the pattern 'abc' nor the
 pattern 'def' will match.

int cre2_partial_match(const char * PATTERN,const 
cre2_string_t * TEXT,cre2_string_t * MATCH,int NMATCH)
int cre2_partial_match_re(cre2_regexp_t * REX,const 
cre2_string_t * TEXT,cre2_string_t * MATCH,int NMATCH)
  • 匹配零終止字符串PATTERN或
    針對緩衝區TEXT 的預編譯正則表達式REX,如果
    TEXT 的子字符串匹配則成功; 這些函數的行爲類似於完全
    匹配的函數,但匹配的文本不需要錨定到
    開頭和結尾。
 For example: the text 'abcDEFghi' matches the pattern 'DEF'
 according to this function.

int cre2_consume(const char * PATTERN,cre2_string_t * 
TEXT,cre2_string_t * MATCH,int NMATCH)
int cre2_consume_re(cre2_regexp_t * REX,cre2_string_t *
TEXT,cre2_string_t * MATCH,int NMATCH)
  • 匹配以\0結尾的字符串PATTERN或者
    針對緩衝區TEXT 的預編譯正則表達式REX,如果
    TEXT 的前綴匹配則成功。TEXT引用的數據結構
    在與
    模式匹配的最後一個字節之後立即變爲引用文本。
For example: the text 'abcDEF' matches the pattern 'abc' according
 to this function; after the call TEXT will reference the text
 'DEF'.

int cre2_find_and_consume(const char * PATTERN,
cre2_string_t * TEXT,cre2_string_t * MATCH,int NMATCH)
int cre2_find_and_consume_re(cre2_regexp_t * REX,
cre2_string_t * TEXT,cre2_string_t * MATCH,int NMATCH)
  • 匹配以零結尾的字符串PATTERN或者
    針對緩衝區TEXT 的預編譯正則表達式REX,如果
    在跳過TEXT中的非匹配前綴之後,TEXT的子字符串匹配,則會成功
    。TEXT引用的數據結構
    在與模式匹配的最後一個字節之後立即變爲引用文本。
 For example: the text 'abcDEFghi' matches the pattern 'DEF'
 according to this function; the prefix 'abc' is skipped; after the
 call TEXT will reference the text 'ghi'.

cre2_replace_re(cre2_regexp_t * REX,
cre2_string_t * TEXT,cre2_string_t * replace)
  • 將符合字符串匹配模式的字符串替換成相應的字符串
    cre2_regexp_t *	rex;
    const char *	pattern	= "hello";
    const char *	text	= "ciao hello salut";
    const char *	replace	= "ohayo";
    cre2_string_t	target	= {
      .data   = text,
      .length = strlen(text)
    };
    cre2_string_t	rewrite	= {
      .data   = replace,
      .length = strlen(replace)
    };
    int			result;
    rex = cre2_new(pattern, strlen(pattern), NULL);
    {
      result = cre2_replace_re(rex, &target, &rewrite);
      if (1 != result)
	goto error;
      if (0 != strncmp("ciao ohayo salut", target.data, target.length))
	goto error;
      if ('\0' != target.data[target.length])
	goto error;
      PRINTF("rewritten to: ");
      FWRITE(target.data, target.length, 1);
      PRINTF("\n");
    }
    cre2_delete(rex);
    free((void *)target.data);

還可以支持全局替換

    cre2_regexp_t *	rex;
    const char *	pattern	= "(壹|貳|叄|肆|伍|陸|柒|捌|玖|拾|佰|仟|萬|萬|億|零)";
    const char *	text	= "ciao 伍 salut 肆陸壹叄";
    const char *	replace	= "sty";
    cre2_string_t	target	= {
      .data   = text,
      .length = strlen(text)
    };
    cre2_string_t	rewrite	= {
      .data   = replace,
      .length = strlen(replace)
    };
    int			result;
    rex = cre2_new(pattern, strlen(pattern), NULL);
    {
      result = cre2_global_replace_re(rex, &target, &rewrite);
      printf("result is %d\n", result);
      if (1 != result)
        printf("replace error \n");
      if (0 != strncmp("ciao sty salut sty", target.data, target.length))
        printf("cmp error \n");
      if ('\0' != target.data[target.length])
        printf("target error \n");
      printf("rewritten to: ");
      printf("%.*s\n", target.length, target.data);
      printf("\n");
    }
    cre2_delete(rex);
    free((void *)target.data);
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章