我有一个应用程序,用户可以在许多地方指定正则表达式。这些在运行应用程序时用于检查文本(例如URL和HTML)是否与正则表达式匹配。用户通常希望能够说文本与ABC匹配且与XYZ 不匹配。为了方便他们这样做,我想在我的应用程序中扩展正则表达式语法,方法是说'并且不包含模式 '。有什么建议可以做到这一点吗?
我的应用程序是用C#.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);
}
有关更好地实施此类延期的任何建议吗?我需要稍微聪明一点,将字符串拆分到¬字符以允许它被转义,所以不要只使用上面简单的Substring()拆分。还有什么需要考虑的吗?
在写这个问题时,我也遇到了this answer,建议使用这样的东西:
^(?=(?:(?!negative pattern).)*$).*?positive pattern
所以我可以建议人们在想要与某些文字不匹配时使用类似的模式,而不是我原来的计划。
这会与我原来的计划相同吗?我认为这是一种相当昂贵的方法,因为我有时会解析大型html文档这可能是一个问题,而我认为我的原始计划会更高效。任何想法(除了明显的:'尝试两个并测量它们!')?
可能与性能有关:有时会出现几个“单词”或更复杂的正则表达式,这些正则表达式不能出现在文本中,例如我上面的例子中的(every | all),但有一些变化。
我知道我的原始方法看起来很奇怪,例如为什么不只有两个正则表达式??但是在我的特定应用程序中,管理员提供了正则表达式,并且很难让他们能够在当前提供的两个正则表达式中提供两个正则表达式。在这种情况下,使用NOT的语法要容易得多 - 只要相信我就可以了。
我有一个应用程序,允许管理员在各种配置点定义正则表达式。正则表达式仅用于检查文本或URL是否与特定模式匹配;不进行替换,也不使用捕获组。但是,他们通常希望指定一个模式,上面写着“ABC不在文本中”。在正则表达式中进行NOT匹配是非常困难的,因此通常的方法是使用两个正则表达式:一个用于指定必须匹配的模式,另一个用于指定不能匹配的模式。如果第一个匹配而第二个匹配则文本匹配。在我的应用程序中,添加在用户现在可以提供的每个地方都有第二个正则表达式的能力将是一项很大的工作,因此我想扩展正则表达式语法,以便说出'而不是包含 图案 ”。
答案 0 :(得分:18)
答案 1 :(得分:9)
您可以使用单个正则表达式轻松完成目标。这是一个演示一种方法的例子。此正则表达式匹配包含"cat"
AND "lion"
和"tiger"
的字符串,但不包含"dog"
或"wolf"
或"hyena"
:
if (Regex.IsMatch(text, @"
# Match string containing all of one set of words but none of another.
^ # anchor to start of string.
# Positive look ahead assertions for required substrings.
(?=.*? cat ) # Assert string has: 'cat'.
(?=.*? lion ) # Assert string has: 'lion'.
(?=.*? tiger ) # Assert string has: 'tiger'.
# Negative look ahead assertions for not-allowed substrings.
(?!.*? dog ) # Assert string does not have: 'dog'.
(?!.*? wolf ) # Assert string does not have: 'wolf'.
(?!.*? hyena ) # Assert string does not have: 'hyena'.
",
RegexOptions.Singleline | RegexOptions.IgnoreCase |
RegexOptions.IgnorePatternWhitespace)) {
// Successful match
} else {
// Match attempt failed
}
您可以看到所需的模式。在组装正则表达式时,请务必通过Regex.escape()方法运行每个用户提供的子字符串,以转义它可能包含的任何元字符(即(
,)
,{{1}等)。此外,为了便于阅读,上述正则表达式以自由间隔模式编写。您的生产正则表达式 NOT 应该使用此模式,否则将忽略用户子字符串中的空格。
如果子字符串只包含真正的单词,您可能希望在每个断言中的每个“单词”之前和之后添加|
个单词边界。
另请注意,使用以下替代语法可以使负面断言更有效:
\b