PCRE风味,261 289 210 184 127 109 71 53 51 44 40字节
对的,这是可能的!
<^<()(?R){2}>\z|\1\Q^<()(?R){2}>\z|\1\Q>
在这里尝试。(但是/
显示为Regex101的分隔符。)
请不要在Regex101页面上进行不必要的编辑(更新)。如果您的编辑实际上并不涉及改进,尝试或测试此正则表达式,则可以对其进行分叉或从其主页创建新的正则表达式。
该版本在Regex101(44字节)上可以更正确地工作:
/^\/()(?R){2}\/\z|\1\Q^\/()(?R){2}\/\z|\1\Q/
在这里尝试。
这比原始版本要简单得多,并且工作起来更像传统的藜。它尝试不使用字符串就定义一个字符串,并在其他地方使用它。因此,可以将其放置在非常接近正则表达式的一端,以减少需要更多字符来定义匹配模式并重复多次的字符数。
说明:
\Q^\/()(?R){2}\/\z|\1\Q
匹配字符串^\/()(?R){2}\/\z|\1\Q
。这使用了一个\Q...\E
不需要关闭的怪癖,而未转义的定界符在中起作用\Q
。这使得某些以前的版本只能在Regex101上运行,而不能在本地运行。但是幸运的是最新版本有效,并且我使用此版本获得了更多字节。
\1
在\Q
与捕获的组1匹配之前。由于此选项中不存在组1,因此只能在递归调用中进行匹配。在递归调用中,它匹配空字符串。
(?R){2}
递归调用整个正则表达式两次,^\/()(?R){2}\/\z|\1\Q
每次都匹配。
()
除了将空字符串捕获到组1中之外,不会执行任何其他操作,这将启用递归调用中的另一个选项。
^\/()(?R){2}\/\z
(?R){2}
从头到尾与添加的定界符匹配。在\/
之前的递归调用还确保这个选项本身并不在递归调用匹配,因为它不会在该字符串的开头。
51个字节,已关闭\Q...\E
:
/\QE\1|^\/(\\)Q(?R){2}z\/\E\1|^\/(\\)Q(?R){2}z\/\z/
在这里尝试。
原始版本,188字节
感谢MartinBüttner打高尔夫球约100个字节!
/^(?=.{173}\Q\2\)){2}.{11}$\E\/\z)((?=(.2.|))\2\/\2\^\2\(\2\?=\2\.\2\{173}\2\\Q\2\\2\2\\\2\)\2\)\2\{2}\2\.\2\{11}\2\$\2\\E\2\\\2\/\2\\z\2\)\2\(\2\(\2\?=\2\(\2\.2\2\.\2\|\2\)\2\)){2}.{11}$/
在这里尝试。
或210个字节,不包含\Q...\E
:
/^(?=.{194}\\2\\.\)\{2}\.\{12}\$\/D$)((?=(.2.|))\2\/\2\^\2\(\2\?=\2\.\2\{194}\2\\\2\\2\2\\\2\\\2\.\2\\\2\)\2\\\2\{2}\2\\\2\.\2\\\2\{12}\2\\\2\$\2\\\2\/D\2\$\2\)\2\(\2\(\2\?=\2\(\2\.2\2\.\2\|\2\)\2\)){2}.{12}$/D
在这里尝试。
扩展版本:
/^(?=.{173}\Q\2\)){2}.{11}$\E\/\z) # Match things near the end.
((?=(.2.|)) # Capture an empty string or \2\ into group 2.
\2\/\2\^\2\(\2\?=\2\.\2\{173}\2\\Q\2\\2\2\\\2\)\2\)\2\{2}\2\.
\2\{11}\2\$\2\\E\2\\\2\/\2\\z\2\) # 1st line escaped.
\2\(\2\(\2\?=\2\(\2\.2\2\.\2\|\2\)\2\) # 2nd line escaped.
){2}
.{11}$/x
像扩展(?=
并\1
取得了所谓的“正规”的表述不再普通,这也使得基内斯可能。反向引用不是常规的,但提前。
说明:
- 我用来
\2\
代替\
转义特殊字符。如果\2
匹配空字符串,\2\x
(其中x
是一个特殊字符)匹配其x
自身。如果\2
匹配\2\
,则\2\x
匹配转义的那一个。\2
组1的两次匹配中的正则表达式可以不同。第一次\2
应匹配空字符串,第二次应匹配\2\
。
\Q\2\)){2}.{11}$\E\/\z
(第1行)从末尾匹配15个字符。和.{11}$
(第7行)从末尾(或尾随换行符之前)匹配11个字符。因此,第二个模式之前的模式必须与第一个模式中的前4个或3个字符\2\.\2\|\2\)\2\)
匹配,因此必须匹配...\2\)
或...\2\
。不能有结尾的换行符,因为最后一个字符应该是)
。并且匹配的文字)
在最右边的文字之前不包含其他文字,因此所有其他字符都必须在中\2
。\2
定义为(.2.|)
,因此只能为\2\
。
- 第一行使整个表达式精确匹配188个字符,因为所有内容的长度都是固定的。组1的两次匹配45 * 2个字符加29次
\2
。第1组之后的内容匹配11个字符。因此,两次的总长度\2
必须恰好是3个字符。\2
第二次知道是3个字符长,第一次必须为空。
- 除了前瞻和以外的所有内容都是第
\2
1组中的文字。\2
已知两次,并且从第一行知道了最后几个字符,此正则表达式恰好匹配一个字符串。
- 马丁·布特纳(MartinBüttner)提出了使用先行捕捉第二组并将其与奎纳部分重叠的想法。这删除了第1组两次之间未以常规方式逃脱的字符,并帮助避免了与我的原始版本中的字符匹配的模式,并大大简化了正则表达式。
不带递归或反向引用的正则表达式,85字节
有人可能会争辩说,具有递归或反向引用的表达式不是真正的“常规”表达式。但是仅具有超前性的表达式仍只能匹配正则语言,尽管如果用传统正则表达式表达的话可能更长。
/(?=.*(\QE\\){2}z\/\z)^\/\(\?\=\.\*\(\\Q.{76}\E\\){2}z\/\z)^\/\(\?\=\.\*\(\\Q.{76}\z/
在这里尝试。
610个字节\Q...\E
(不打高尔夫球):
/^(?=.{610}$)(?=.{71}(\(\.\{8\}\)\?\\.[^(]*){57}\)\{2\}\.\{12\}\$\/D$)((.{8})?\/(.{8})?\^(.{8})?\((.{8})?\?=(.{8})?\.(.{8})?\{610(.{8})?\}(.{8})?\$(.{8})?\)(.{8})?\((.{8})?\?=(.{8})?\.(.{8})?\{71(.{8})?\}(.{8})?\((.{8})?\\(.{8})?\((.{8})?\\(.{8})?\.(.{8})?\\(.{8})?\{8(.{8})?\\(.{8})?\}(.{8})?\\(.{8})?\)(.{8})?\\(.{8})?\?(.{8})?\\(.{8})?\\(.{8})?\.(.{8})?\[(.{8})?\^(.{8})?\((.{8})?\](.{8})?\*(.{8})?\)(.{8})?\{57(.{8})?\}(.{8})?\\(.{8})?\)(.{8})?\\(.{8})?\{2(.{8})?\\(.{8})?\}(.{8})?\\(.{8})?\.(.{8})?\\(.{8})?\{12(.{8})?\\(.{8})?\}(.{8})?\\(.{8})?\$(.{8})?\\(.{8})?\/D(.{8})?\$(.{8})?\)(.{8})?\(){2}.{12}$/D
在这里尝试。
这个想法是相似的。
/^(?=.{610}$)(?=.{71}(\(\.\{8\}\)\?\\.[^(]*){57}\)\{2\}\.\{12\}\$\/D$)
((.{8})?\/(.{8})?\^(.{8})?\((.{8})?\?=(.{8})?\.(.{8})?\{610(.{8})?\}(.{8})?\$(.{8})?\)
(.{8})?\((.{8})?\?=(.{8})?\.(.{8})?\{71(.{8})?\}
(.{8})?\((.{8})?\\(.{8})?\((.{8})?\\(.{8})?\.(.{8})?\\(.{8})?\{8(.{8})?\\(.{8})?\}
(.{8})?\\(.{8})?\)(.{8})?\\(.{8})?\?(.{8})?\\(.{8})?\\
(.{8})?\.(.{8})?\[(.{8})?\^(.{8})?\((.{8})?\](.{8})?\*(.{8})?\)(.{8})?\{57(.{8})?\}
(.{8})?\\(.{8})?\)(.{8})?\\(.{8})?\{2(.{8})?\\(.{8})?\}
(.{8})?\\(.{8})?\.(.{8})?\\(.{8})?\{12(.{8})?\\(.{8})?\}
(.{8})?\\(.{8})?\$(.{8})?\\(.{8})?\/D(.{8})?\$(.{8})?\)(.{8})?\(){2}.{12}$/D
基本正则表达式
如果不允许前瞻,那么我现在能做的就是:
/\\(\\\(\\\\){2}/
哪个匹配
\\(\\\(\\
如果{m,n}
不允许使用量词,那是不可能的,因为没有什么可以匹配一个字符串,也不能匹配比其更长的字符串。当然,人们仍然可以发明\q
只匹配的东西/\q/
,并且仍然用该正则表达式来表达。但是显然,主要的实现都不能支持这种情况。