我需要根据一组模式匹配一个结构,并为每个匹配采取一些行动。
模式应该支持通配符,我需要确定哪些模式匹配传入结构,例如:
action=new_user email=*
action=del_user email=*
action=* email=*@gmail.com
action=new_user email=*@hotmail.com
可以实时添加/删除这些模式。可以有数千个连接,每个都有自己的模式,我需要通知每个连接我收到了匹配的结构。模式不是完全正则表达式,我只需要将字符串与通配符*匹配(简单匹配任意数量的字符)。
当服务器收到带有结构action=new_user email=testuser@gmail.com
的消息(让我们称之为消息A)并且我需要发现模式1和3匹配此消息时,我应该对每个匹配的模式执行操作(发送此结构A到相应的连接)。
如何以最有效的方式完成这项工作?我可以迭代这些模式并逐个检查,但我正在寻找更有效和线程安全的方法来做到这一点。可能有可能将这些模式分组以减少检查..任何建议如何做到这一点?
UPD :请注意我想要匹配乘法模式(千)aganst固定“字符串”(实际上是结构),反之亦然。换句话说,我想找到哪些模式适合给定的结构A.
答案 0 :(得分:1)
将模式转换为正则表达式,并使用RE2匹配它们,{{3}}是用C ++编写的,是最快的模式之一。
答案 1 :(得分:0)
实际上,如果我理解正确,第四种模式是多余的,因为第一种模式更通用,并且包括与第四种模式匹配的每个字符串。这只剩下3种模式,可以通过这个函数轻松检查:
bool matches(const char* name, const char* email)
{
return strstr(name, "new_user") || strstr(name, "del_user") || strstr(email, "@gmail.com");
}
如果您希望解析整个字符串,而不仅仅是匹配action
和email
的值,那么以下函数应该可以解决这个问题:
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
函数here。
答案 2 :(得分: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';
}
答案 3 :(得分: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]
但最好仍然使用正则表达式,以防将来需要的东西比野猫更多。