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 を対応する接続​​に送信します)。

これを最も効率的な方法で行うにはどうすればよいですか? このパターンを反復して 1 つずつチェックすることはできますが、これを行うためのより効率的でスレッドセーフな方法を探しています。チェックを減らすためにこれらのパターンをグループ化することはおそらく可能です..これを行う方法について何か提案はありますか?

UPD : 固定された「文字列」(実際には構造体) に対して複数のパターン (数千)を一致させる必要があることに注意してください。その逆ではありません。言い換えれば、与えられた構造Aにどのパターンが適合するかを見つけたい.

4

4 に答える 4

0

これはandのみ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

実際、私の理解が正しければ、4 番目のパターンは冗長です。最初のパターンの方が一般的で、4 番目のパターンに一致するすべての文字列が含まれているからです。これにより、この関数で簡単に確認できる 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機能について読むことができます。

于 2013-07-24T21:48:38.213 に答える
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 に答える