Я пишу своего рода клиент 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);Это не только сработало, но на самом деле было быстрее и уменьшило влияние на мой рендеринг текста. Может кто-нибудь объяснить новичку в регулярных выражениях, почему? :)





Не делая подробного анализа, я бы предположил, что это быстрее из-за вопросительных знаков. Это позволяет регулярному выражению быть «ленивым» и останавливаться, как только их достаточно для сопоставления, вместо того, чтобы проверять, совпадает ли остальная часть входных данных.
Я не совсем доволен этим ответом, потому что это в основном относится к вопросительным знакам после * или +. Если бы я был более знаком с вводом, это могло бы иметь для меня больше смысла.
(Кроме того, для форматирования кода вы можете выделить весь свой код и нажать Ctrl + K, чтобы добавить четыре необходимых пробела.)
Причина, по которой №1 работает медленнее, заключается в том, что [\ d;] + является жадным квантификатором. Используя +? или же *? собирается провести ленивую количественную оценку. См. MSDN - квантификаторы для получения дополнительной информации.
Вы можете попробовать:
"(\e\[(\d{1,2};)*?[mz]?)?"
Это может быть быстрее для вас.
Вы действительно хотите запустить регулярное выражение дважды? Не проверив (плохо меня) я бы подумал, что это сработает хорошо:
public static string StripStringFormating(string formattedString)
{
return rTest.Replace(formattedString, string.Empty);
}
Если это так, вы должны увидеть, что он работает ~ в два раза быстрее ...
Я не уверен, поможет ли это в том, над чем вы работаете, но давно я написал регулярное выражение для анализа графических файлов 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.]
Спасибо за этот ответ, я сохраню это выражение под рукой, когда, без сомнения, вернусь и позже пересмотрю код на предмет возможных улучшений. :) Как я обнаружил, «большие» регулярные выражения обычно быстрее меньших.
Меня также интересует все, что вы делаете с кодами ANSI в .NET. В настоящее время я переделываю свой сайт в rails, а не в .NET, но мне всегда любопытно посмотреть, как люди могут использовать .NET для интерпретации ANSI.
Если подумать об этом сейчас, это имеет смысл: запуск регулярного выражения в строке без совпадений - это то же самое, что сначала выполнить проверку, чтобы увидеть, совпадает ли она вообще. Вы получите тот же результат!