it-swarm.asia

一个永远不会被任何东西匹配的正则表达式

这可能听起来像一个愚蠢的问题,但我与我的一些开发人员进行了长时间的谈话,这听起来很有趣。

所以;你的想法是什么 - 正则表达式是什么样的,永远不会被任何字符串匹配!

编辑 :为什么我要这个?好吧,首先是因为我发现想到这样一个表达式很有趣,其次因为我需要它来制作一个脚本。

在该脚本中,我将字典定义为Dictionary<string, Regex>。如您所见,它包含一个字符串和一个表达式。

基于该字典,我创建的方法都使用这个字典作为他们应该如何完成工作的参考,其中一个匹配正则表达式与解析的日志文件。

如果表达式匹配,则添加另一个Dictionary<string, long>表达式返回的值。因此,为了捕获与字典中的表达式不匹配的任何日志消息,我创建了一个名为“unknown”的新组。

对于这个组,添加了与其他任何东西不匹配的所有内容。但为了防止“未知”表达式(偶然)不匹配日志消息,我不得不创建一个绝对不会匹配的表达式,无论我给它什么字符串。

因此,你有理由这个“不是一个真正的问题”......

111
Florian Peschka

这其实很简单, 虽然它取决于实现/标志*:

$a

将在字符串结尾后匹配字符a。祝好运。

警告:
这个表达式很昂贵 - 它将扫描整行,找到行尾锚点,然后才找不到a并返回否定匹配。 (有关详细信息,请参阅下面的评论。)


* 最初我对多线模式正则表达式没有太多考虑,其中$也匹配一行的结尾。实际上,它会匹配空字符串在换行符之前,因此像a这样的普通字符永远不会出现在$之后。

61
Ferdinand Beyer

利用negative lookahead

>>> import re
>>> x=r'(?!x)x'
>>> r=re.compile(x)
>>> r.match('')
>>> r.match('x')
>>> r.match('y')

这个RE在术语上是矛盾的,因此永远不会匹配任何东西。

注意:
在Python中, re.match() 隐式地将一个字符串开头的锚点(\A)添加到正则表达式的开头。此锚点对性能很重要:没有它,将扫描整个字符串。那些不使用Python的人会想要明确地添加锚点:

\A(?!x)x
70
Alex Martelli

环视四周:

(?=a)b

对于正则表达式新手:正向前看(?=a)确保下一个字符是a,但不会更改搜索位置(或在匹配的字符串中包含“a”)。现在确认下一个字符是a,正则表达式的剩余部分(b)仅在下一个字符为b时才匹配。因此,只有当一个字符同时是ab时,此正则表达式才匹配。

33
Amarghosh

错过了一个:

^\b$

它无法匹配,因为空字符串不包含Word边界。在Python 2.5中测试。

31
Mark Byers

a\bc,其中\b是与Word边界匹配的零宽度表达式。

它不能出现在Word的中间,我们强迫它。

29
P Shved

$.

.^

$.^

(?!)

19
Knio

Perl 5.10支持称为“动词”的特殊控制字,它包含在(*...)序列中。 (与(?...)特殊序列比较。)其中,它包括 (*FAIL)动词 它立即从正则表达式返回。

请注意,动词也会在不久之后在PCRE中实现,因此您可以在PHP或其他使用PCRE库的语言中使用它们。 (但是你不能用Python或Ruby。他们使用自己的引擎。)

10
Kang Seonghoon

最大匹配

a++a

至少有一个a后跟任意数量的a,没有回溯。然后尝试再匹配a

或独立子表达式

这相当于将a+放在一个独立的子表达式中,然后是另一个a

(?>a+)a
10
Brad Gilbert
\B\b

\b匹配Word边界 - 字母与非字母(或字符串边界)之间的位置。
\B是它的补充 - 它匹配两个字母之间或非字母之间的位置。

他们在一起无法匹配任何位置。

也可以看看:

9
Kobi

$^或者(?!)怎么样?

8
Bob

这似乎有效:

$.
8
Jerry Fernholz

这对于Python和许多其他语言都不起作用,但在Javascript正则表达式中,[]是一个无法匹配的有效字符类。所以无论输入什么,以下都应该立即失败:

var noMatch = /^[]/;

我比/$a/更喜欢它,因为对我而言,它清楚地传达了它的意图。至于你什么时候需要它,我需要它,因为我需要基于用户输入的动态编译模式的后备。当模式无效时,我需要用一个不匹配的模式替换它。简化,它看起来像这样:

try {
    var matchPattern = new RegExp(someUserInput);
}
catch (e) {
    matchPattern = noMatch;
}
4
undefined

Python不接受它,但Perl会:

Perl -ne 'print if /(w\1w)/'

这个正则表达式应该(理论上)尝试匹配无限(偶数)个ws,因为第一个组(()s)会自我修复。 Perl似乎没有发出任何警告,即使在use strict; use warnings;下,所以我认为它至少是有效的,而且我的(最小)测试无法匹配任何东西,所以我提交它以供你的批评。

4
Chris Lutz

[^\d\D](?=a)ba$aa^a

4
Bart Kiers

最快的将是:

r = re.compile(r'a^')
r.match('whatever')

'a'可以是任何非特殊字符('x','y')。 Knio的实现可能会更加纯粹,但是对于所有字符串而言,这一点对于所有字符串都会更快,而不是以“a”开头,因为它在第一个字符之后而不是在第二个字符之后不匹配。

4
Adam Nelson

这么多好的答案!

与@nivk的答案类似,我想分享Perl对于永不匹配的正则表达式的不同变体的性能比较。

  1. 输入:伪随机ascii字符串(25,000个不同的行,长度8-16):

正则表达速度:

Total for   \A(?!x)x: 69.675450 s, 1435225 lines/s
Total for       a\bc: 71.164469 s, 1405195 lines/s
Total for    (?>a+)a: 71.218324 s, 1404133 lines/s
Total for       a++a: 71.331362 s, 1401907 lines/s
Total for         $a: 72.567302 s, 1378031 lines/s
Total for     (?=a)b: 72.842308 s, 1372828 lines/s
Total for     (?!x)x: 72.948911 s, 1370822 lines/s
Total for       ^\b$: 79.417197 s, 1259173 lines/s
Total for         $.: 88.727839 s, 1127041 lines/s
Total for       (?!): 111.272815 s, 898692 lines/s
Total for         .^: 115.298849 s, 867311 lines/s
Total for    (*FAIL): 350.409864 s, 285380 lines/s
  1. 输入:/ usr/share/dict/words(100,000英文单词)。

正则表达速度:

Total for   \A(?!x)x: 128.336729 s, 1564805 lines/s
Total for     (?!x)x: 132.138544 s, 1519783 lines/s
Total for       a++a: 133.144501 s, 1508301 lines/s
Total for    (?>a+)a: 133.394062 s, 1505479 lines/s
Total for       a\bc: 134.643127 s, 1491513 lines/s
Total for     (?=a)b: 137.877110 s, 1456528 lines/s
Total for         $a: 152.215523 s, 1319326 lines/s
Total for       ^\b$: 153.727954 s, 1306346 lines/s
Total for         $.: 170.780654 s, 1175906 lines/s
Total for       (?!): 209.800379 s, 957205 lines/s
Total for         .^: 217.943800 s, 921439 lines/s
Total for    (*FAIL): 661.598302 s, 303540 lines/s

(英特尔i5-3320M上的Ubuntu,Linux内核4.13,Perl 5.26)

2
filiprem

在看到一些这些伟大的答案后, @ arantius的评论 (关于时间$x vs x^ vs (?!x)x)对当前接受的答案让我想要计算到目前为止给出的一些解决方案。

使用@ arantius的275k行标准,我在Python中运行了以下测试(v3.5.2,IPython 6.2.1)。

TL; DR:'x^''x\by'是最快的因子至少~16,与@ arantius的发现相反,(?!x)x属于最慢(慢37倍)。所以速度问题肯定是依赖于实现的。如果速度对您很重要,请在提交前自行测试您的系统。

更新: 时间'x^''a^'之间显然存在很大差异。请参阅 这个问题 获取更多信息,以及之前使用a而不是x编辑较慢的时序。

In [1]: import re

In [2]: with open('/tmp/longfile.txt') as f:
   ...:     longfile = f.read()
   ...:     

In [3]: len(re.findall('\n',longfile))
Out[3]: 275000

In [4]: len(longfile)
Out[4]: 24733175

In [5]: for regex in ('x^','.^','$x','$.','$x^','$.^','$^','(?!x)x','(?!)','(?=x)y','(?=x)(?!x)',r'x\by',r'x\bx',r'^\b$'
    ...: ,r'\B\b',r'\ZNEVERMATCH\A',r'\Z\A'):
    ...:     print('-'*72)
    ...:     print(regex)
    ...:     %timeit re.search(regex,longfile)
    ...:     
------------------------------------------------------------------------
x^
6.98 ms ± 58.4 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
------------------------------------------------------------------------
.^
155 ms ± 960 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
------------------------------------------------------------------------
$x
111 ms ± 2.12 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
------------------------------------------------------------------------
$.
111 ms ± 1.76 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
------------------------------------------------------------------------
$x^
112 ms ± 1.14 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
------------------------------------------------------------------------
$.^
113 ms ± 1.44 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
------------------------------------------------------------------------
$^
111 ms ± 839 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
------------------------------------------------------------------------
(?!x)x
257 ms ± 5.03 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
------------------------------------------------------------------------
(?!)
203 ms ± 1.56 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
------------------------------------------------------------------------
(?=x)y
204 ms ± 4.84 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
------------------------------------------------------------------------
(?=x)(?!x)
210 ms ± 1.66 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
------------------------------------------------------------------------
x\by
7.41 ms ± 122 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
------------------------------------------------------------------------
x\bx
7.42 ms ± 110 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
------------------------------------------------------------------------
^\b$
108 ms ± 1.05 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
------------------------------------------------------------------------
\B\b
387 ms ± 5.77 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
------------------------------------------------------------------------
\ZNEVERMATCH\A
112 ms ± 1.52 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
------------------------------------------------------------------------
\Z\A
112 ms ± 1.38 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

第一次运行它时,我忘了raw最后3个表达式,所以'\b'被解释为'\x08',即退格符。但令我惊讶的是,'a\x08c'比之前的最快结果更快!公平地说,它仍然会匹配该文本,但我认为它仍然值得注意,因为我不确定为什么它更快。

In [6]: for regex in ('x\by','x\bx','^\b$','\B\b'):
    ...:     print('-'*72)
    ...:     print(regex, repr(regex))
    ...:     %timeit re.search(regex,longfile)
    ...:     print(re.search(regex,longfile))
    ...:     
------------------------------------------------------------------------
y 'x\x08y'
5.32 ms ± 46.1 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
None
------------------------------------------------------------------------
x 'x\x08x'
5.34 ms ± 66.3 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
None
------------------------------------------------------------------------
$ '^\x08$'
122 ms ± 1.05 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
None
------------------------------------------------------------------------
\ '\\B\x08'
300 ms ± 4.11 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
None

我的测试文件是使用 “......可读内容和无重复行”的公式创建的 (在Ubuntu 16.04上):

$ Ruby -e 'a=STDIN.readlines;275000.times do;b=[];Rand(20).times do; b << a[Rand(a.size)].chomp end; puts b.join(" "); end' < /usr/share/dict/words > /tmp/longfile.txt

$ head -n5 /tmp/longfile.txt 
unavailable speedometer's garbling Zambia subcontracted fullbacks Belmont mantra's
pizzicatos carotids bitch Hernandez renovate leopard Knuth coarsen
Ramada flu occupies drippings peaces siroccos Bartók upside twiggier configurable perpetuates tapering pint paralyzed
vibraphone stoppered weirdest dispute clergy's getup perusal fork
nighties resurgence chafe
2
nivk

我相信

\Z RE FAILS! \A

甚至包括正则表达式包括MULTILINE,DOTALL等标志的情况。

>>> import re
>>> x=re.compile(r"\Z RE FAILS! \A")
>>> x.match('')
>>> x.match(' RE FAILS! ')
>>>

我相信(但我没有对它进行基准测试)无论\Z\A之间的字符串长度(> 0)如何,失败的时间应该是不变的。

2
tzot

也许这个?

/$.+^/
1
Dan Breen
(*FAIL)

要么

(*F)

使用PCRE和Perl,您可以使用此回溯控制动词来强制模式立即失败。

1
Casimir et Hippolyte
'[^0-9a-zA-Z...]*'

并用所有可打印的符号替换...;)。这是一个文本文件。

0
Drakosha

空正则表达式

永远不匹配任何东西的最好的正则表达式是一个空的正则表达式。但我不确定所有正则表达式引擎都会接受这一点。

不可能的正则表达式

另一个解决方案是创建一个不可能的正则表达式。我发现$-^只需要两个步骤来计算,无论文本大小如何( https://regex101.com/r/yjcs1Z/1 )。

以供参考:

  • $^$.需要36步才能计算 - > O(1)
  • \b\B对我的样本采取1507步,并随着字符串中的字符数增加 - > O(n)

关于这个问题更受欢迎的主题:

0
aeon

那么使用一个总是错误的if语句而不是正则表达式呢?在javascript中:

var willAlwaysFalse=false;
if(willAlwaysFalse)
{
}
else
{
}
0
Graviton