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

Я пишу своего рода клиент 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);

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

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

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

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
16
0
4 721
4

Ответы 4

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

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

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

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

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

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

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

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

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

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

Если подумать об этом сейчас, это имеет смысл: запуск регулярного выражения в строке без совпадений - это то же самое, что сначала выполнить проверку, чтобы увидеть, совпадает ли она вообще. Вы получите тот же результат!

Nidonocu 13.09.2008 11:17

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

Спасибо за этот ответ, я сохраню это выражение под рукой, когда, без сомнения, вернусь и позже пересмотрю код на предмет возможных улучшений. :) Как я обнаружил, «большие» регулярные выражения обычно быстрее меньших.

Nidonocu 18.09.2008 01:22

Меня также интересует все, что вы делаете с кодами ANSI в .NET. В настоящее время я переделываю свой сайт в rails, а не в .NET, но мне всегда любопытно посмотреть, как люди могут использовать .NET для интерпретации ANSI.

Doug Moore 18.09.2008 01:25

Другие вопросы по теме