.NET Regex для белых символов - PullRequest
4 голосов
/ 20 августа 2009

Рассмотрим алгоритм, который должен определить, содержит ли string какие-либо символы, кроме символов из белого списка.

Белый список выглядит так:

-. AbcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ ÇüéâäàåçêëèïîìÄÅÉæÆôöòûùÖÜáíóúñÑÀÁÂÃÈÊËÌÍÎÏÐÒÓÔÕØÙÚÛÝßãðõøýþÿ

Примечание: пробелы и апострофы должны быть включены в этот белый список.

Обычно это статический метод, но он будет преобразован в метод расширения.

private bool ContainsAllWhitelistedCharacters(string input)
{
  string regExPattern="";// the whitelist
  return Regex.IsMatch(input, regExPattern);
}

Вопросы:

Спасибо за комментарии к производительности всем ответчикам. Производительность не проблема. Качество, удобочитаемость и ремонтопригодность есть! Меньше кода = меньше шансов на дефекты, ИМО.

Вопрос:

Каким должен быть этот шаблон регулярного выражения белого списка?

Ответы [ 4 ]

5 голосов
/ 20 августа 2009

Почему это должно быть регулярное выражение?

private bool ContainsAllWhitelistedCharacters(string input)
{
  string whitelist = "abcdefg...";
  foreach (char c in input) {
    if (whitelist.IndexOf(c) == -1)
      return false;
  }
  return true;
}

Нет необходимости прыгать прямо в регулярные выражения, если вы не знаете, как реализовать тот, который вам нужен, и вы не профилировали этот раздел кода и обнаружили, что вам нужна дополнительная производительность.

4 голосов
/ 20 августа 2009

Вы можете сопоставить шаблон, используя следующее:

^([\-\.a-zA-Z ÇüéâäàåçêëèïîíìÄÅÉæÆôöòûùÖÜáíóúñÑÀÁÂÃÈÊËÌÍÎÏÐÒÓÔÕØÙÚÛÝßãðõøýþÿ]+)$

Сделайте это методом расширения с помощью:

public static bool IsValidCustom(this string value)
{
    string regExPattern="^([\-\.a-zA-Z ÇüéâäàåçêëèïîíìÄÅÉæÆôöòûùÖÜáíóúñÑÀÁÂÃÈÊËÌÍÎÏÐÒÓÔÕØÙÚÛÝßãðõøýþÿ]+)$";
    return Regex.IsMatch(input, regExPattern);
}

Я не могу придумать простой способ создания поддерживаемого диапазона с расширенными символами, поскольку порядок символов не очевиден.

0 голосов
/ 20 августа 2009

Обратите внимание, что я не рекомендую это, если производительность на самом деле не является проблемой, но я подумал, что хотел бы отметить, что, даже включая предварительную компиляцию регулярного выражения, вы можете сделать это немного быстрее:

сравнения:

static readonly Regex r = new Regex(
  @"^(['\-\.a-zA-Z ÇüéâäàåçêëèïîíìÄÅÉæÆôöòûùÖÜáíóúñÑ"+
   "ÀÁÂÃÈÊËÌÍÎÏÐÒÓÔÕØÙÚÛÝßãðõøýþÿ]+)$");

public bool IsValidCustom(string value)
{
  return r.IsMatch(value);
}

с:

private bool ContainsAllWhitelistedCharacters(string input)
{
    foreach (var c in input)
    {
        switch (c)
        {
            case '\u0020': continue; 
            case '\u0027': continue; 
            case '\u002D': continue; 
            case '\u002E': continue; 
            case '\u0041': continue; 
            case '\u0042': continue; 
            case '\u0043': continue; 
            case '\u0044': continue; 
            case '\u0045': continue; 
            case '\u0046': continue; 
            case '\u0047': continue; 
            case '\u0048': continue; 
            case '\u0049': continue; 
            case '\u004A': continue; 
            case '\u004B': continue; 
            case '\u004C': continue; 
            case '\u004D': continue; 
            case '\u004E': continue; 
            case '\u004F': continue; 
            case '\u0050': continue; 
            case '\u0051': continue; 
            case '\u0052': continue; 
            case '\u0053': continue; 
            case '\u0054': continue; 
            case '\u0055': continue; 
            case '\u0056': continue; 
            case '\u0057': continue; 
            case '\u0058': continue; 
            case '\u0059': continue; 
            case '\u005A': continue; 
            case '\u0061': continue; 
            case '\u0062': continue; 
            case '\u0063': continue; 
            case '\u0064': continue; 
            case '\u0065': continue; 
            case '\u0066': continue; 
            case '\u0067': continue; 
            case '\u0068': continue; 
            case '\u0069': continue; 
            case '\u006A': continue; 
            case '\u006B': continue; 
            case '\u006C': continue; 
            case '\u006D': continue; 
            case '\u006E': continue; 
            case '\u006F': continue; 
            case '\u0070': continue; 
            case '\u0071': continue; 
            case '\u0072': continue; 
            case '\u0073': continue; 
            case '\u0074': continue; 
            case '\u0075': continue; 
            case '\u0076': continue; 
            case '\u0077': continue; 
            case '\u0078': continue; 
            case '\u0079': continue; 
            case '\u007A': continue; 
            case '\u00C0': continue; 
            case '\u00C1': continue; 
            case '\u00C2': continue; 
            case '\u00C3': continue; 
            case '\u00C4': continue; 
            case '\u00C5': continue; 
            case '\u00C6': continue; 
            case '\u00C7': continue; 
            case '\u00C8': continue; 
            case '\u00C9': continue; 
            case '\u00CA': continue; 
            case '\u00CB': continue; 
            case '\u00CC': continue; 
            case '\u00CD': continue; 
            case '\u00CE': continue; 
            case '\u00CF': continue; 
            case '\u00D0': continue; 
            case '\u00D1': continue; 
            case '\u00D2': continue; 
            case '\u00D3': continue; 
            case '\u00D4': continue; 
            case '\u00D5': continue; 
            case '\u00D6': continue; 
            case '\u00D8': continue; 
            case '\u00D9': continue; 
            case '\u00DA': continue; 
            case '\u00DB': continue; 
            case '\u00DC': continue; 
            case '\u00DD': continue; 
            case '\u00DF': continue; 
            case '\u00E0': continue; 
            case '\u00E1': continue; 
            case '\u00E2': continue; 
            case '\u00E3': continue; 
            case '\u00E4': continue; 
            case '\u00E5': continue; 
            case '\u00E6': continue; 
            case '\u00E7': continue; 
            case '\u00E8': continue; 
            case '\u00E9': continue; 
            case '\u00EA': continue; 
            case '\u00EB': continue; 
            case '\u00EC': continue; 
            case '\u00ED': continue; 
            case '\u00EE': continue; 
            case '\u00EF': continue; 
            case '\u00F0': continue; 
            case '\u00F1': continue; 
            case '\u00F2': continue; 
            case '\u00F3': continue; 
            case '\u00F4': continue; 
            case '\u00F5': continue; 
            case '\u00F6': continue; 
            case '\u00F8': continue; 
            case '\u00F9': continue; 
            case '\u00FA': continue; 
            case '\u00FB': continue; 
            case '\u00FC': continue; 
            case '\u00FD': continue; 
            case '\u00FE': continue; 
            case '\u00FF': continue;        
        }
        return false;     
    }    return true; // empty string is true    
}

При очень быстром тестировании на совокупности слов со скоростью прохождения около 60% я получаю примерно в 8 раз больше скорости при таком подходе.

На самом деле это не так уж и плохо читаемо, чем регулярное выражение без escape-символов!

0 голосов
/ 20 августа 2009

Я не знаю, как реализован бэкэнд регулярных выражений, но, возможно, наиболее эффективно использовать следующее для соответствия чему-либо, кроме вашего списка:

private bool ContainsAllWhitelistedCharacters(string input)
{
   Regex r = new Regex("[^ your list of chars ]");
   return !r.IsMatch(test)
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...