2012-01-20 2 views
6

У меня в классе около 100 Regex звонки, каждая обложка вызова различного типа данных в текстовом протоколе, но у меня много файлов и на основе аналитики regex выполнил 88% выполнения моего кода.Более быстрая замена для Regex

Многие такой код:

{ 
    Match m_said = Regex.Match(line, @"(.*) said,", RegexOptions.IgnoreCase); 
    if (m_said.Success) 
    { 
    string playername = ma.Groups[1].Value; 
    // some action 
    return true; 
    } 
} 

{ 
    Match ma = Regex.Match(line, @"(.*) is connected", RegexOptions.IgnoreCase); 
    if (ma.Success) 
    { 
    string playername = ma.Groups[1].Value; 
    // some action 
    return true; 
    } 
} 
{ 
    Match ma = Regex.Match(line, @"(.*): brings in for (.*)", RegexOptions.IgnoreCase); 
    if (ma.Success) 
    { 
    string playername = ma.Groups[1].Value; 
    long amount = Detect_Value(ma.Groups[2].Value, line); 
    // some action 
    return true; 
    } 
} 

Есть ли способ заменить Regex с каким-либо другим быстрее решения?

+1

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

ответ

8

Для регулярных выражений, которые проверены в цикле, часто быстрее прекомпиляций их вне цикла и просто теста их внутри цикла.

Вам необходимо объявить различные регулярные выражения сначала соответствующими шаблонами и только вызывать Match() с текстом для проверки на втором шаге.

+1

Не имеет ли класс RegEx кеш? –

+0

@HenkHolterman: Действительно. Я только что проверил это в документе. (Я больше привык к PCRE, который не обеспечивает механизм кэширования.) Кэш должен работать для статических 'Regex.Match()' вызовов, сделанных OP. Или слишком много регулярных выражений, и 'Regex.CacheSize' - это путь для изучения, чтобы улучшить производительность (но я сомневаюсь)? – Seki

+0

Спасибо, что человек работает в 10 раз быстрее ;-)))) – Svisstack

1

Вы можете попробовать заранее компиляции Regex или рассмотреть вопрос об объединении всех индивидуальных Regex выражения в один (монстр) Regex:

Match m_said = Regex.Match(line, 
      @"(.*) (said|(is connected)|...|...),", 
      RegexOptions.IgnoreCase); 

Вы можете проверить вторую группу захвата, чтобы определить, какой тип матча произошло.

+0

Это единственный ответ, который я вижу, что попытки сканирования файлов (ов) только один раз. –

+0

В зависимости от возможных текстов может возникнуть проблема с @ "(. *) Указанной« версией alltogether: что, если «User17 сказал« Я уже говорил это! »' - регулярное выражение найдет неправильное «сказал» –

+1

Я не могу этого сделать, строки имеют разные форматы, кроме, например, команды X Y. – Svisstack

1

Я знаю, что Regex может сделать много вещей, но здесь является эталон с Regex против char.Split против String.Split

http://www.dotnetperls.com/split в разделе Бенчмарки

+1

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

+0

вы правы об этом -_- –

3

Помимо прекомпиляции вашего регулярного выражения, вы могли бы выигрыш (возможно, гораздо больше), благодаря написанию более точного регулярного выражения. В связи с этим, .* почти всегда плохой выбор:

(.*) is connected означает: во-первых соответствует всю строку (это .* часть), а затем вернуться назад на один символ в то время, пока это не возможно, чтобы соответствовать is connected.

Теперь, если строка не очень короткая, или is connected появляется очень близко к концу строки, это много назад, которое стоит времени.

Итак, если вы можете уточнить, что такое разрешенное совпадение, вы можете повысить производительность.

Например, если допускаются только буквенно-цифровые символы, то (\w+) is connected будет хорошо. Если это любые символы без пробелов, используйте (\S+) is connected. И т.д., в зависимости от правил для действительного соответствия.

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

+0

Gah! Я собирался написать комментарий об одной из сильных сторон регулярных выражений, заключающейся в том, что они могут быть скомпилированы в DFA, и не требуется никакого возврата. Но затем я просмотрел документы для реализации регулярных выражений .NET и [* вы правы! *] (Http://msdn.microsoft.com/en-us/library/dsy130b4.aspx) –

2

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

private static readonly Regex xmlRegex = new Regex("YOUR EXPRESSION", RegexOptions.Compiled); 

В вашей выборке, каждый раз, когда метод используется это компилирует "выражение, но это как ненужное выражение является константным.Теперь он скомпилирован скомпилирован только один раз. Недостатком является то, что при первом обращении к выражению это немного медленнее.

+1

спасибо ;-) это хороший ответ с этими статическими полями – Svisstack

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