2009-08-20 3 views
4

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

Белый список выглядит следующим образом:

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

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

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

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

соображение:

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

Вопрос:

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

+2

Если вы создаете метод расширения для 'string', как это, он предполагает, что все строки подчиняются белым спискам за то, что они могут и не могут содержать, но это неверно. –

+0

@ 28: спасибо за комментарий. Я понимаю, что метод будет доступен для всех членов 'string'. Разработчику было бы разумно называть метод расширения, как и его реализацию как утилиты. –

+0

@pcampbell: вы должны создать неизменяемую структуру, содержащую строку, которая, как известно, не содержит никаких плохих символов (отмечена в конструкторе). Таким образом, в отличие от класса «Путь», вы можете работать с строкой, не выполняя проверку O (n) на наличие плохих символов. –

ответ

4

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

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

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

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

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

+0

Внимание с кодировками. – Havenard

+0

Я думаю, что вышеприведенный шаблон потребует небольшой настройки, чтобы пустые значения. Также рассмотрите возможность использования встроенного символьного класса «\ w» вместо того, чтобы перечислить алфавит всех поддерживаемых языков. Это приведет к подчеркиваниям и цифрам, которые затем потребуют от второго RegEx исключить, но сэкономит много потенциального обслуживания по дороге, пытаясь повторно изобрести класс персонажа. – richardtallent

+1

Я тестировал его, и он работает для пробелов. Это твердый код значений, пробел включен после Z. Только диапазоны являются символами из a-z и A-Z – Kelsey

5

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

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

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

+0

Umm ... это не работает, так почему все upvotes? Он не поймает, если в строке есть недопустимые символы. – Kelsey

+0

Спасибо, Марк. К сожалению, это предложение 'IndexOfAny' не возвращает отфильтрованные символы без символов, такие как« _ »или« 5 ». –

+0

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

0

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

private bool ContainsAllWhitelistedCharacters(string input) 
{ 
    Regex r = new Regex("[^ your list of chars ]"); 
    return !r.IsMatch(test) 
} 
+6

Двойные негативы не путают. –

+0

Согласен, я предложил сделать это так * предполагая * это более эффективное регулярное выражение в C#. Кто-нибудь знает, верно это или нет? Меня интересует ответ. –

0

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

сравнения:

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!

Смежные вопросы