Regex簡易實現

來源:互聯網
上載者:User
Regex

       雖然Regex在 U n i x/Linux程式設計環境裡隨處可見,但在其他的系統裡使用得卻沒有這麼廣泛。一個Regex本身也是一個字元序列,它定義了一集能與之匹配的字串。大部分字元只是簡單地與相同字元匹配,例如Regex a b c將匹配同樣的字元序列,無論它出現在什麼地方。在這裡還有幾個元字元(meta character),它們分別表示重複、成組或者位置。

       在 Unix通行的Regex中,字元 ^表示字串開始, $表示字串結束。這樣, ^ x只能與位於字串開始處的 x匹配,x $只能匹配結尾的 x,^ x $只能匹配單個字元的串裡的 x,而^ $只能匹配空串。字元“ .”能與任一字元匹配。所以,模式 x . y能匹配x a y、x 2 y等等,但它不能匹配 x y或xaby。顯然 ^.$能夠與任何單個字元的串匹配。寫在方括弧 []裡的一組字元能與這組字元中的任一個相匹配。這樣 [0123456789]
能與任何數字匹配。這個模式也可以簡寫為 [0-9]。

       最有名的Regex工具就是linux系統裡面的 g r e p程式。這個程式是一個極好的例子,它確實顯示出記法的價值。 g r e p將一個Regex作用於輸入的每一行,列印出所有包含匹配字串的行。這是一個非常簡單的規範,但是,藉助於Regex的威力,它能夠完成許多我們天天都能遇到的工作。

簡易實現

       先從代碼入手,下面是Regex匹配的主函數match,接收參數為匹配模式regexp和文本text。     

/*match匹配regexp與text,如果不匹配則text往後移動,繼續下一次匹配,直到匹配成功即返回,否則返回0。特例是regexp以^開頭,表示需要以此作為開始,所以這時regexp只能從頭匹配text,不能從匹配text的其他位置*/int match(char *regexp, char *text){    if (regexp[0] == '^')        return matchhere(regexp+1, text);    do {        if (matchhere(regexp, text))            return 1;    } while (*text++ != '\0');    return 0;}

       如果Regex的開頭是 ^,那麼本文必須從起始處與運算式的其餘部分匹配。否則,我們就沿著串走下去,用 m a t c h h e r e看本文是否能在某個位置上匹配。一旦發現了匹配,工作就完成了。注意這裡 d o - w h i l e的使用,有些運算式能與Null 字元串匹配 (例如: $ 能夠在字串的末尾與Null 字元串匹配, *能匹配任意個數的字元,包括 0個)。所以,即使遇到了Null 字元串,我們也還需要調用 matchhere。

       遞迴函式matchhere完成大部分的匹配工作:

int matchhere(char *regexp, char *text){    if (regexp[0] == '\0')        return 1;    if (regexp[0]=='$' && regexp[1]=='\0')        return *text == '\0';    if (regexp[1] == '*')        return matchstar(regexp[0], regexp+2, text);    if (*text!='\0' && (regexp[0]=='.' || regexp[0]==*text))        return matchhere(regexp+1, text+1);    return 0;}

       如果regexp[0]=='\0',表示已經匹配到末尾,則匹配成功,返回1.如果運算式的最後是 $,匹配成功的條件是本文也到達了末尾;即判斷*text=='\0'。如果本文text也到了末尾,則匹配成功,否則失敗。如果本文沒有到末尾,且regexp[0]==*text或者regexp=='.'(.表示匹配任一字元),則遞迴調用matchhere繼續下一次匹配。如果regexp[1]=='*',則過程稍顯複雜,在運算式開始處遇到了帶星號字元,例如
x *。這時我們調用 m a t c h s t a r,其第一個參數是星號的參數 (在上面的例子裡是 x),隨後的參數是位於星號之後的模式,以及對應的本文串。

int matchstar(int c, char *regexp, char *text){    do {        if (matchhere(regexp, text))            return 1;    } while (*text!='\0' && (*text++==c || c=='.'));    return 0;}

執行個體

1)char *regexp="abc", text="dagabcdefg",  匹配成功。 2)char *regexp="^abc", *text="abcdefg",   匹配成功。

3)char *regexp="^abc", *text="bcdefgabc", 匹配失敗。4) char *regexp="abc$", *text="defghabc",  匹配成功。

完整代碼

#include <stdio.h>int matchstar(int c, char *regexp, char *text);int matchhere(char *regexp, char *text);int match(char *regexp, char *text);int match(char *regexp, char *text){    if (regexp[0] == '^')        return matchhere(regexp+1, text);    do {        if (matchhere(regexp, text))            return 1;    } while (*text++ != '\0');    return 0;}int matchhere(char *regexp, char *text){    if (regexp[0] == '\0')        return 1;    if (regexp[0]=='$' && regexp[1]=='\0')        return *text == '\0';    if (regexp[1] == '*')        return matchstar(regexp[0], regexp+2, text);    if (*text!='\0' && (regexp[0]=='.' || regexp[0]==*text))        return matchhere(regexp+1, text+1);    return 0;}int matchstar(int c, char *regexp, char *text){    do {        if (matchhere(regexp, text))            return 1;    } while (*text!='\0' && (*text++==c || c=='.'));    return 0;}int main(){    char *regexp = "xa$";    char *text = "bcabcdefgya";    int ret = match(regexp, text);    printf("%d\n", ret);    return 0;}

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.