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

Я пишу клиент Telnet сорта в С#, и часть того, что мне нужно проанализировать, это 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);

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

Ответы

Ответ 1

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

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

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

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

Ответ 2

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

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

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

Ответ 3

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

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

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

Ответ 4

Я не уверен, поможет ли это тому, над чем вы работаете, но давно я написал регулярное выражение для анализа графических файлов 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.]