正则表达式简易实现

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/ssjhust123/article/details/7760119

正则表达式

       虽然正则表达式在 U n i x/Linux程序设计环境里随处可见,但在其他的系统里使用得却没有这么广泛。一个正则表达式本身也是一个字符序列,它定义了一集能与之匹配的字符串。大部分字符只是简单地与相同字符匹配,例如正则表达式 a b c将匹配同样的字符序列,无论它出现在什么地方。在这里还有几个元字符(meta character),它们分别表示重复、成组或者位置。

       在 Unix通行的正则表达式中,字符 ^表示字符串开始, $表示字符串结束。这样, ^ x只能与位于字符串开始处的 x匹配,x $只能匹配结尾的 x,^ x $只能匹配单个字符的串里的 x,而^ $只能匹配空串。字符“ .”能与任意字符匹配。所以,模式 x . y能匹配x a y、x 2 y等等,但它不能匹配 x y或xaby。显然 ^.$能够与任何单个字符的串匹配。写在方括号 []里的一组字符能与这组字符中的任一个相匹配。这样 [0123456789] 能与任何数字匹配。这个模式也可以简写为 [0-9]。

       最有名的正则表达式工具就是linux系统里面的 g r e p程序。这个程序是一个极好的例子,它确实显示出记法的价值。 g r e p将一个正则表达式作用于输入的每一行,打印出所有包含匹配字符串的行。这是一个非常简单的规范,但是,借助于正则表达式的威力,它能够完成许多我们天天都能遇到的工作。

简易实现

       先从代码入手,下面是正则表达式匹配的主函数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;
}
       如果正则表达式的开头是 ^,那么正文必须从起始处与表达式的其余部分匹配。否则,我们就沿着串走下去,用 m a t c h h e r e看正文是否能在某个位置上匹配。一旦发现了匹配,工作就完成了。注意这里 d o - w h i l e的使用,有些表达式能与空字符串匹配 (例如: $ 能够在字符串的末尾与空字符串匹配, *能匹配任意个数的字符,包括 0个)。所以,即使遇到了空字符串,我们也还需要调用 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;
}
 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值