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

Я пишу своего рода клиент Telnet на C #, и часть того, что я должен проанализировать, это escape-последовательности ANSI / VT100, в частности, только те, которые используются для цвета и форматирования (подробно здесь ).

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

    
public static string StripStringFormating(string formattedString)
{
    if (rTest.IsMatch(formattedString))
        return rTest.Replace(formattedString, string.Empty);
    else
        return formattedString;
}

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

static Regex rText = new Regex(@"\e\[[\d;]+m", RegexOptions.Compiled);

Однако это не удалось, если управляющий код был неполным из-за ошибки на сервере. Тогда это было предложено, но мой друг предупредил, что это может быть медленнее (это также соответствует другому условию (z), с которым я могу столкнуться позже):

static Regex rTest = 
              new Regex(@"(\e(\[([\d;]*[mz]?))?)?", RegexOptions.Compiled);

Это не только сработало, но и ускорило и уменьшило влияние на мой рендеринг текста. Может кто-нибудь объяснить новичку регулярного выражения, почему? :)

7.08.2008 15:43:11
4 ОТВЕТА

Без подробного анализа, я думаю, что это быстрее из-за вопросительных знаков. Они позволяют регулярному выражению быть «ленивым» и останавливаются, как только их хватит для сравнения, вместо того, чтобы проверять, совпадают ли остальные входные данные.

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

(Кроме того, для форматирования кода вы можете выбрать весь свой код и нажать Ctrl+, Kчтобы добавить четыре требуемых пробела.)

1
6.02.2013 05:53:21

Причина, по которой # 1 медленнее, заключается в том, что [\ d;] + является жадным квантификатором. Используя +? или *? собирается сделать ленивый количественный анализ. Посмотрите MSDN - Квантификаторы для получения дополнительной информации.

Вы можете попробовать:

"(\e\[(\d{1,2};)*?[mz]?)?"

Это может быть быстрее для вас.

3
7.08.2008 16:47:48

Вы действительно хотите дважды запустить регулярное выражение? Не проверив (плохо меня), я бы подумал, что это будет хорошо работать:

public static string StripStringFormating(string formattedString)
{    
    return rTest.Replace(formattedString, string.Empty);
}

Если это произойдет, вы должны увидеть, что он работает в два раза быстрее ...

4
31.10.2011 14:06:33
Думая об этом сейчас, это имеет смысл, запуск регулярного выражения в строке без совпадений - это то же самое, что сначала выполнить проверку, чтобы увидеть, совпадает ли она вообще. Вы получаете тот же результат!
Nidonocu 13.09.2008 07:17:10

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

(?s)(?:\e\[(?:(\d+);?)*([A-Za-z])(.*?))(?=\e\[|\z)

Он вернет каждый код и связанный с ним текст.

Строка ввода:

<ESC>[1;32mThis is bright green.<ESC>[0m This is the default color.

Полученные результаты:

[ [1, 32], m, This is bright green.]
[0, m, This is the default color.]
1
28.11.2012 15:50:06
Спасибо за этот ответ, я буду держать это выражение под рукой, когда, без сомнения, вернусь и рассмотрю код позже для возможных улучшений. :) Как я обнаружил, «большие» регулярные выражения, как правило, быстрее, чем меньшие.
Nidonocu 17.09.2008 21:22:00
Мне также интересно все, что вы делаете с кодами ANSI в .NET. В настоящее время я переделываю свой сайт в рельсах, а не в .NET, но мне всегда любопытно посмотреть, как люди могут использовать .NET для интерпретации ANSI.
lordscarlet 17.09.2008 21:25:02