用于"AND NOT"操作的正则表达式

Jos*_*nig 25 regex logical-operators

我正在寻找一个通用的正则表达式构造来匹配模式中的所有内容x EXCEPT匹配模式y.这很难完全和简洁地解释......请参阅Material Nonimplication以获得正式定义.

例如,匹配任何单词字符(\w)除了'p'.注意我从一个较大的集合(所有单词字符)中减去一个小集合(字母'p').我不能只是说,[^p]因为这没有考虑到只有单词字符的更大限制集.对于这个小例子,当然,我可以手动重建类似的东西[a-oq-zA-OQ-Z0-9_],这是一种痛苦但可行的.但我正在寻找一个更通用的结构,以便至少大的正集可以是一个更复杂的表达式.喜欢匹配,((?<=(so|me|^))big(com?pl{1,3}ex([pA]t{2}ern)除非它以"我的"开头.

编辑:我意识到这是一个不好的例子,因为在开始或结束时排除东西是负面前瞻和后视表达式工作的情况.(波希米亚人,我仍然给你一个赞成说明这一点).那么......在中间的某个地方排除包含"我的"的匹配怎么样?...我仍然在寻找一个通用的构造,就像一个正则表达式相当于下面的伪sql

select [captures] from [input]
where (
    input MATCHES [pattern1]
    AND NOT capture MATCHES [pattern2]
)
Run Code Online (Sandbox Code Playgroud)

如果答案是"它不存在,这就是为什么......"我也想知道这一点.

编辑2:如果我想定义自己的函数来执行此操作,那就像(这里是C#LINQ版本):

public static Match[] RegexMNI(string input, 
                               string positivePattern, 
                               string negativePattern) {
    return (from Match m in Regex.Matches(input, positivePattern)
            where !Regex.IsMatch(m.Value, negativePattern)
            select m).ToArray();
}
Run Code Online (Sandbox Code Playgroud)

我仍然只是想知道是否有一个本机正则表达式构造可以做到这一点.

Boh*_*ian 21

这将匹配任何字符一个词,是不是一个p:

((?=[^p])\w)
Run Code Online (Sandbox Code Playgroud)

要解决您的示例,请在输入中的任何位置使用"我的"的否定预测,即(?!.*My):

^(?!.*My)((?<=(so|me|^))big(com?pl{1,3}ex([pA]t{2}ern)
Run Code Online (Sandbox Code Playgroud)

请注意启动输入的锚点,^这是使其工作所必需的.


Kus*_*nda 16

我想知道为什么人们试图在大型的整体正则表达式中做复杂的事情?

为什么不能将问题分解为子部分,然后制作非常简单的正则表达式来单独匹配?在这种情况下,首先匹配\w,然后匹配[^p]第一个匹配是否成功.Perl(和其他语言)允许构建看起来非常复杂的正则表达式,这些正则表达式允许您在一个大的blobby-regex中完成您需要做的事情(或者,它可能是一个简短而快速的加密正则表达式) ,但是为了那些需要阅读(并维护!)代码的人,你需要完全记录它.最好是从一开始就让它易于理解.

对不起,咆哮.

  • 是的,Zawinski效应使使用RE扩大了问题的数量。(我最喜欢的是有人要求RE接受已写入XML文档中的有效IEEE双精度值……) (2认同)

ste*_*ema 6

在你的编辑后,它仍然是负面的前瞻,但还有一个额外的量词.

如果要确保整个字符串不包含"我的",则可以执行此操作

(?!.*My)^.*$
Run Code Online (Sandbox Code Playgroud)

在Regexr上看到它

这将匹配任何字符序列(.*在末尾),并且(?!.*My).*当字符串中的任何位置有"我的"时,开头将失败.

如果你想匹配任何不完全"我的"的东西,那么使用锚点

(?!^My$).*
Run Code Online (Sandbox Code Playgroud)