0

我需要将结构与一组模式进行匹配,并为每次匹配采取一些措施。

模式应该支持通配符,我需要确定哪些模式与传入结构匹配,示例集:

action=new_user email=*
action=del_user email=*
action=* email=*@gmail.com
action=new_user email=*@hotmail.com

可以实时添加/删除这些模式。可能有数千个连接,每个都有自己的模式,我需要通知每个连接我收到了一个匹配的结构。模式不是完全正则表达式,我只需要将字符串与通配符 * 匹配(简单匹配任意数量的字符)。

当服务器接收到具有结构的消息(我们称之为消息 A)action=new_user email=testuser@gmail.com并且我需要找出模式 1 和 3 与此消息匹配时,我应该对每个匹配的模式执行操作(将此结构 A 发送到相应的连接)。

如何以最有效的方式做到这一点?我可以迭代这些模式并逐一检查,但我正在寻找更有效和线程安全的方法来做到这一点。可能可以对这些模式进行分组以减少检查。有什么建议可以做到这一点吗?

UPD:请注意我想要匹配乘法模式(数千)与固定的“字符串”(实际上是一个结构),反之亦然。换句话说,我想找出哪些模式适合给定的结构 A。

4

4 回答 4

1

将模式转换为正则表达式,并使用RE2匹配它们,它是用 C++ 编写的,是最快的之一。

于 2013-07-25T21:44:50.297 回答
0

这仅strglobmatch支持。*?

#include <string.h>  /* memcmp, index */

char* strfixstr(char *s1, char *needle, int needle_len) {
  int l1;
  if (!needle_len) return (char *) s1;
  if (needle_len==1) return index(s1, needle[0]);
  l1 = strlen(s1);
  while (l1 >= needle_len) {
    l1--;
    if (0==memcmp(s1,needle,needle_len)) return (char *) s1;
    s1++;
  }
  return 0;
}

int strglobmatch(char *str, char *glob) {
  /* Test: strglobmatch("almamxyz","?lmam*??") */
  int min;
  while (glob[0]!='\0') {
    if (glob[0]!='*') {
      if ((glob[0]=='?') ? (str[0]=='\0') : (str[0]!=glob[0])) return 0;
      glob++; str++;
    } else { /* a greedy search is adequate here */
      min=0;
      while (glob[0]=='*' || glob[0]=='?') min+= *glob++=='?';
      while (min--!=0) if (*str++=='\0') return 0;
      min=0; while (glob[0]!='*' && glob[0]!='?' && glob[0]!='\0') { glob++; min++; }
      if (min==0) return 1; /* glob ends with star */
      if (!(str=strfixstr(str, glob-min, min))) return 0;
      str+=min;
    }
  }
  return str[0]=='\0';
}
于 2013-07-25T07:37:02.113 回答
0

如果你想要的只是通配符匹配,那么你可以试试这个算法。关键是检查所有不是通配符的子字符串是否在字符串中。

patterns = ["*@gmail.com", "akalenuk@*", "a*a@*", "ak*@gmail.*", "ak*@hotmail.*", "*@*.ua"]
string = "akalenuk@gmail.com"
preprocessed_patterns = [p.split('*') for p in patterns]


def match(s, pp):
    i = 0
    for w in pp:
        wi = s.find(w, i)
        if wi == -1:
            return False
        i = wi+len(w) 
    return i == len(s) or pp[-1] == ''

print [match(string, pp) for pp in preprocessed_patterns]

但最好还是使用正则表达式,以防您将来需要的不仅仅是通配符。

于 2013-07-25T07:45:51.393 回答
0

实际上,如果我理解正确的话,第四个模式是多余的,因为第一个模式更通用,并且包括与第四个匹配的每个字符串。只剩下 3 种模式,可以通过此函数轻松检查:

bool matches(const char* name, const char* email)
{
    return strstr(name, "new_user") || strstr(name, "del_user") || strstr(email, "@gmail.com");
}

如果您更喜欢解析整个字符串,而不仅仅是匹配 and 的值actionemail那么下面的函数应该可以解决问题:

bool matches2(const char* str)
{
    bool match = strstr(str, "action=new_user ") || strstr(str, "action=del_user ");
    if (!match)
    {
        const char* emailPtr = strstr(str, "email=");
        if (emailPtr)
        {
            match = strstr(emailPtr, "@gmail.com");
        }
    }
    return match;
}

请注意,您作为参数输入的字符串必须使用\0. 您可以在此处阅读有关strstr功能的信息。

于 2013-07-24T21:48:38.213 回答