适应adblock plus 规则的简单正则表达式匹配

adblock plus定义的广告过滤列表非常好用,这里分析一下adblock plus的广告过滤规则

开始表示注释

* 通配符,匹配任何字符串

@@ 以此开头表示白名单,

| 以此开始或者结束表示开始处或者结束处严格匹配,没有其他内容了

|| 以此开头会忽略协议规则进行匹配,比如忽略httphttps

^ 分隔符匹配除数字,字母,-.,%以外的其他字符

$ 指明后面的是过滤类型,比如是是image还是script

 

按照adblock plus的说法,这些最终都转换成了正则表达式来处理,具体怎么实现不是很清楚。

对于大多数情况来说运行最耗时间的就是匹配问题,类型,以及协议信息可以根据url分析出来,很容易分离,

因此这里重点介绍如何实现最核心的*^的匹配,通过一个patternStep来减小嵌套次数

/*

  get a much bigger step for *.

  */

static inline int  patternStep( const char * s, const  char * p)

{

    //这里可以根据下一个字符多跳几个

    char temp[8];

    int step=0;

    const char * t=p;

    while(*t!='*' && *t!='^' && *t!='\0')

    {

        step++;

        t++;

    }

    if(!step) //防止只有一个通配符的情况比如^,*

        return 1;

    memset(temp,0,sizeof(temp));

    strncpy(temp,p,min(sizeof(temp)-1,step));

    printf("temp=%s,step=%d\n",temp,step);

    const char * res=strfind(s,temp);

    if(!res) //没有找到

        return strlen(s); //移动真整个字符串

    else

        return max(1,res-s); //找到第一个匹配的字符串的位置

}

/*

   test if a given string  and a pattern  matches use adblock plus rule

   give a string s and a pattern p ,

   if they match,return 1, then return 0

   */

bool adbMatch(const char *  s,  const char *  p,bool caseSensitivie=true) {

    for (;;) {

        switch(*p++) {

            case '*' :  // match 0-n of any characters

                //这里可以根据下一个字符多跳几个

                if (!*p) return true; // do trailing * quickly

                while (!adbMatch(s, p,caseSensitivie))

                {

                    if(!*s) return false;

                    s+=patternStep(s,p);

                }

                return true;

            case '^':

                if(isSeperator(*s))

                {

                    s++;

                    break;

                }

                else

                    return false;//expect a sepetor,

            case '\0':  // end of pattern

                return !*s;

            default  :

                if (getCaseChar(*s++,caseSensitivie) !=

                    getCaseChar(*(p-1),caseSensitivie)) return false;

                break;

        }

    }

}

原文地址:https://www.cnblogs.com/baizx/p/1752658.html