У меня есть приложение, в котором пользователи могут указывать регулярные выражения в нескольких местах. Они используются при запуске приложения для проверки соответствия текста (например, URL-адресов и HTML) регулярным выражениям. Часто пользователи хотят иметь возможность сказать, где текст соответствует ABC и не соответствует XYZ. Чтобы облегчить им это сделать, я думаю о распространении синтаксиса регулярных выражений в моем приложении с возможностью сказать "и не содержит шаблон". Любые предложения по хорошему способу сделать это?
Мое приложение написано на С#.NET 3.5.
Мой план (до того, как я получил удивительные ответы на этот вопрос...)
В настоящее время я думаю об использовании символа ¬: что-либо до того, как символ ¬ является нормальным регулярным выражением, что-либо после символа ¬ является регулярным выражением, которое не может соответствовать в тестируемом тексте.
Поэтому я мог бы использовать некоторые регулярные выражения, подобные этому (надуманному) примеру:
on (this|that|these) day(s)?¬(every|all) day(s) ?
Что, например, будет соответствовать "в этот день мужчина сказал...", но не будет соответствовать "в этот день и каждый день после того, как будет...".
В моем коде, обрабатывающем регулярное выражение, я просто разделил две части регулярного выражения и обрабатывал их отдельно, например:
public bool IsMatchExtended(string textToTest, string extendedRegex)
{
int notPosition = extendedRegex.IndexOf('¬');
// Just a normal regex:
if (notPosition==-1)
return Regex.IsMatch(textToTest, extendedRegex);
// Use a positive (normal) regex and a negative one
string positiveRegex = extendedRegex.Substring(0, notPosition);
string negativeRegex = extendedRegex.Substring(notPosition + 1, extendedRegex.Length - notPosition - 1);
return Regex.IsMatch(textToTest, positiveRegex) && !Regex.IsMatch(textToTest, negativeRegex);
}
Любые предложения по лучшему способу реализации такого расширения? Мне нужно быть немного умнее о разделении строки на символ ¬, чтобы она могла быть экранирована, поэтому не просто использовать простое разделение подстроки() выше. Что еще нужно учитывать?
Альтернативный план
При написании этого вопроса я также встретил этот ответ, который предлагает использовать что-то вроде этого:
^(?=(?:(?!negative pattern).)*$).*?positive pattern
Поэтому я мог бы просто посоветовать людям использовать шаблон, например, вместо моего первоначального плана, когда они хотят НЕ соответствовать определенному тексту.
Будет ли это эквивалентно моему первоначальному плану? Я думаю, что это довольно дорогостоящий способ сделать это мудрый, и поскольку я иногда разбираю большие html-документы, это может быть проблемой, тогда как я полагаю, что мой первоначальный план был бы более результативным. Любые мысли (помимо очевидного: "попробуйте оба и измерьте их!" )?
Возможно, уместно для производительности: иногда будет несколько слов или более сложное регулярное выражение, которое не может быть в тексте, например (каждый | все) в моем примере выше, но с несколькими вариантами.
Почему!?
Я знаю, что мой оригинальный подход кажется странным, например. почему не просто два регулярных выражения!? Но в моем конкретном приложении администраторы предоставляют регулярные выражения, и было бы довольно сложно дать им возможность предоставлять два регулярных выражения везде, где они могут его предоставить. Намного проще в этом случае иметь синтаксис для NOT - просто доверьтесь мне в этой точке.
У меня есть приложение, которое позволяет администраторам определять регулярные выражения в разных точках конфигурации. Регулярные выражения используются только для проверки соответствия текста или URL определенного шаблона; замены не выполняются, и группы захвата не используются. Однако часто они хотели бы указать шаблон, в котором говорится: "Где ABC отсутствует в тексте". Как правило, трудно выполнить НЕ соответствие в регулярных выражениях, поэтому обычный способ состоит в том, чтобы иметь два регулярных выражения: один для указания шаблона, который должен быть сопоставлен, и один для указания шаблона, который не должен быть сопоставлен. Если первый соответствует, а второй - нет, текст соответствует. В моем приложении было бы очень много работы, чтобы добавить возможность иметь второе регулярное выражение в каждом месте, которое пользователи могут предоставить сейчас, поэтому я хотел бы расширить синтаксис регулярных выражений, чтобы сказать " и не содержать шаблон.