如果一个字符跟随另一个字符(可选),我不想匹配

问题描述:

我想匹配“错误”的任何变体(让我们假设整个棋盘上不区分大小写),其中可能有也可能不跟随字符,并且可能有或没有“s”。如果一个字符跟随另一个字符(可选),我不想匹配

例如,如果它具有以下,返回匹配的行:

text error: more text 
text error more text 
text errors more text 
text errors(more text 
text errors: more text 
text errors:more text 

但如果有一个等号后不久,我不希望它返回的行。例如:

text errors= more text 

基本上,在“error”或“errors”后面有一个“=”符号时,它总是“错误”。

我无法想出比这更:

(?i)errors?[^\=] 

不区分大小写,字符E,R,R,O,R,也许一个s,而不是接着是“= “是我阅读的方式。

1 sample text, more text, errors=123456 more text more text 
2 drops=0 link status good errors=0 adapter 
3 Error: process failed to start 
4 process [ERROR] failed 
5 this line might have both ERROR and error=5555 and more text 
6 there might be a line that has error=0x02343329 ERROR and more text 

我想线3,4,5,和6被返回,而不是1或2。

不具有成功。我在这里先向您的帮助表示感谢。

+0

'errors?'使整个字符串'errors'可选。这可能是为什么3-6没有返回。你会想'错误(s?)'而不是。 – dzieciou

+1

也等号需要转义,所以你应该有'='而不是'\ ='。 – dzieciou

+2

@dzieciou“错误?使整个字符串错误可选。” fge

零宽度预测是一个很好的答案。尝试:?

(?i)(?!errors?=)error 

其中“(?!errors?=)”是指“不期而遇提前检查不匹配‘错误=’

更新: 这是通过在原有的正则表达式(?i)errors?[^\=]解释的问题问题: 的并发症是如何以及何时“贪婪”(人perlre)不是因为贪婪,因为它可能是,引用:

By default, a quantified subpattern is "greedy", that is, it will match as many times as possible (given a particular starting location) while still allowing the rest of the pattern to match.

注意句子的第二部分的原始表达式(?i)errors?[^\=]将匹配“errors =”(或“errors”),因为“s?”允许匹配0次以允许“[^ =]”匹配“s”。 这就是为什么它匹配6个编号的行。

当这样的匹配(*,+,?等)被拒绝时,正则表达式引擎内发生的事情称为“回溯”,匹配备份并尝试不同的路径,以查看是否更好地匹配整个整体正则表达式是可能的。独立的子表达式(?>),lookarounds(?=)(?!)及其消极形式可以防止或限制回溯,就像使用交替一样,似乎每个人都有不同的偏好,因为我认为他们大多数都出现在某处。尽管目前为止没有人使用“所有格”为您的原始正则表达式提供最小的无回溯变化?+形式:

errors?+[^\=] 
+0

这一个似乎工作没有失败。我看到了很多我想看到的东西。谢谢。 – harperville

+0

我不确定这是否会允许包含错误和错误=的行,然后将其返回。我对错误很感兴趣,只要它没有跟随=,但如果错误和错误=在同一行,我仍然希望它返回。 – harperville

+0

@haperville,您是否在http://regex101.com/r/xV2aG6上尝试了答案? – dzieciou

尝试使用向前断言:

(?i)errors?(?!\=) 
+0

如果全部是关于找到匹配的行而不是匹配的子字符串,那么这将如何改变结果? – dzieciou

+0

将文本拆分\ n,然后将每行与正则表达式匹配。 –

+0

我的意思是,'(?i)错误?(?!\ =)'和'(?i)错误?[^ \ =]'之间没有区别。 – dzieciou

怎么样的逻辑OR?

(?i)error[^s=]|errors[^=] 
+0

表达式的第一部分将与'error ='匹配,这不是OP想要的。 – dzieciou

+0

@dzieciou我想你可能误解了他写的东西。例如,查看包含子字符串'error ='的测试用例#5和#6。请注意,OP说#5和#6是他想要返回的行。也许你正在考虑'错误='(即复数)? – David

+0

这个问题似乎令人困惑,这就是为什么我们以不同的方式解释它。我明白第五个返回,因为它包含字符串'错误'。另外OP写道:“不区分大小写,字符e,r,r,o,r,也许是s,而不是后面跟着”=“是我阅读的方式。” – dzieciou

尝试:

(?i)\berror(?!s?=) 

字锚,随后error,只要它不跟一个可选的s然后等号。

(?!...)是负先行,也是在这个意义上的锚定(如^$),它不消耗文本(它是一个零宽度断言)。

这么多的答案,如此接近他们所有人。你想要的是:/error(?!s=)/im

你不需要使用内联组,而是使用/ i标志。

我可能错过了你的问题,我不确定。但是,如果您也想禁止error=blah,则只需使用/error(?!s?=)/im

演示+解释:http://regex101.com/r/oE1eQ9

+0

+1用于在线演示结果。 – dzieciou

哦,亲爱的。很多人认为他们知道正则表达式!

在自己的正则表达式(?i)errors?[^\=](其中,正如有人所说,=不需要逃避,但它并没有坏处)[^\=]并不颇有意味“后面没有一个等号”,它意味着“之后一个不是等号的字符“。除非error位于字符串末尾,否则两者相同,因此'error' =~ (?i)errors?[^\=]返回false。

“后面没有一个等号”需要负先行,所以乍一看它看起来像你想(?i)errors?(?!=),但如果正则表达式引擎找到errors=它会走回头路,尽量不选购s匹配,看是否它可以得到整个模式匹配的方式,然后将成功,因为errorserror后面没有等号。

要解决此问题,您需要无回溯构造(?>...),一旦找到匹配项就不允许回溯。正则表达式(?i)(?>errors?)(?!=)做你所需要的。

最后,为了允许拒绝等于“errorerrors之后不久”,在它之前需要一些可选的空白区域,给出(?i)(?>errors?)(?!\s*=)

此程序演示

use strict; 
use warnings; 

while (<DATA>) { 
    chomp; 
    printf "%-70s %s\n", $_, /(?i)(?>errors?)(?!\s*=)/ ? 'YES' : 'NO'; 
} 

__DATA__ 
text error: more text 
text error more text 
text errors more text 
text errors(more text 
text errors: more text 
text errors:more text 
text errors= more tex 
text errors = more tex 
text error= more tex 
text error = more tex 
1 sample text, more text, errors=123456 more text more text 
2 drops=0 link status good errors=0 adapter 
3 Error: process failed to start 
4 process [ERROR] failed 
5 this line might have both ERROR and error=5555 and more text 
6 there might be a line that has error=0x02343329 ERROR and more text 

输出

text error: more text             YES 
text error more text             YES 
text errors more text             YES 
text errors(more text             YES 
text errors: more text             YES 
text errors:more text             YES 
text errors= more tex             NO 
text errors = more tex             NO 
text error= more tex             NO 
text error = more tex             NO 
1 sample text, more text, errors=123456 more text more text   NO 
2 drops=0 link status good errors=0 adapter       NO 
3 Error: process failed to start          YES 
4 process [ERROR] failed            YES 
5 this line might have both ERROR and error=5555 and more text   YES 
6 there might be a line that has error=0x02343329 ERROR and more text YES 

所以,你想匹配 “错误”,只要它不跟 “=” 或 “S =”。这是很简单的:

/error(?!=|s=)/ 

你甚至可以把它写成

/error(?!s?=)/ 

如果你真的想如果可能的话(为了设置${^MATCH}什么的),则可以使用

匹配的“错误”
/error(?![s=])|errors(?!=)/ 

您遇到问题,因为/ [^=] /匹配项“s”。