我正在使用大量的正则表达式,并且偶然发现了一个问题,即真正可以用正则表达式描述不。
我想到的第一个例子是匹配像XOOXXXOOOOXXXXX...
这样的字符串。这将是由X
和O
的交替序列组成的字符串,其中每个子部分仅由字符X
或O
组成,比预先设置的要长另一个角色的序列。
有人可以解释正则表达式的正式限制吗?我知道这可能是一个相当学术性的问题,但我是一个好奇的人; - )
修改 由于我是一个php人员,我对PCRE标准所描述的正则表达式特别感兴趣,如下所述:http://php.net/manual/en/reference.pcre.pattern.syntax.php 我知道PCRE允许很多不属于原始正则表达式的东西,比如反向引用。
平衡括号的数学似乎是一般情况下正则表达式无法匹配的一个例子,但可以使用PCRE进行匹配(参见http://sandbox.onlinephpfunctions.com/code/fd12b580bb9ad7a19e226219d5146322a41c6e47实例):
$data = array('()', '(())', ')(', '(((()', '(((((((((())))))))))', '()()');
$regex = '/^((?:[^()]|\((?1)\))*+)$/';
foreach($data as $d) {
echo "$d matched by regex: " . (preg_match($regex, $d) ? 'yes' : 'no') . "\n";
}
答案 0 :(得分:4)
我想到的第一个例子是匹配像
XOOXXXOOOOXXXXX...
这样的字符串。这将是由X
和O
的交替序列组成的字符串,其中每个子部分仅由字符X
或O
组成,比预先设置的要长另一个角色的序列。
是的,可以做到。
为了匹配非空的x序列,然后是更多的o,我们可以使用类似于平衡括号正则表达式的方法:
(x(?1)?o)o+
为了匹配一个x和o的字符串,使得x的任何序列后跟一个更长的o序列(除了可选的最后一个),我们可以构建模式#1:
^o*(?:(x(?1)?o)o+)*x*$
当然,我们还需要一个带有x和o的模式#2的变体:
^x*(?:(o(?1)?x)x+)*o*$
要匹配满足上述两个条件的x和o的字符串,我们可以将模式#2转换为正向前瞻断言,并在模式#3中重新编号捕获组:
^(?=o*(?:(x(?1)?o)o+)*x*$)x*(?:(o(?2)?x)x+)*o*$
至于主要问题。 。 。我确信PCRE可以匹配任何无上下文的语言,因为支持 n 捕获组的(?n)
意味着你可以基本上为每个非终端创建一个子程序。例如,这种无上下文语法:
可以写成:
(a(?2)b|)
(c(?1)d|e(?2)f)
要将它组合成一个正则表达式,我们可以将它们全部连接起来,但是除了起始非终端之外,追加{0}
,然后添加^
和$
:< / p>
^(a(?2)b|)(c(?1)d|e(?2)f){0}$
但正如您从第一个示例中看到的那样,PCRE也可以匹配一些非上下文语言。 (另一个例子是 a n b n c n ,这是非上下文语言的典型示例。您可以通过组合PCRE将其与PCRE匹配EM>一 名词 b'/ EM> 名词 C < / em> m ,其中 m b < / em> n c n 使用前瞻性断言。虽然交集两种常规语言必然是常规语言,两种无上下文语言的交集不必然是无上下文的;但是两个PCRE 定义的语言的交集可以定义通过PCRE。)
答案 1 :(得分:1)
正则表达式可以识别的所有语言的集合被称为“regular languages”。
下一个最复杂的语言是context-free languages。它们无法被任何正则表达式解析。标准的例子是“所有平衡的括号” - 所以“()()”和“(())”但不是“(()”。
无上下文语言的另一个好例子是HTML。
答案 2 :(得分:0)
我没有确切的证据表明,通过递归,平衡组,自引用组以及将文本附加到要测试的字符串中,这些都是不可能实现的。我很高兴能在所有这些或全部问题上被证明是错误的,因为我会学到一些东西!
1)数学非常糟糕。
例如,我认为使用PCRE来检测上升的数字序列是不可能的:也就是说,在“ 1 2 7 97 315 316 ...”上返回true。
2)我不确定是否有可能匹配从1连续增加的序列 ,例如“ 1 2 3 ...”,而没有详尽列出所有/1( 2( 3(...)?)?)?/
之类的可能性直到您要检查的最大长度。
您可以通过在被测字符串中添加已知文本来使其正常工作(例如http://www.rexegg.com/regex-trick-line-numbers.html通过在文件末尾添加一系列数字来使其工作)。但是作为原始正则表达式,只有通过强制才能实现简单的数学运算。
3)我相信它将失败的另一个示例是“匹配总和为N的任何序列”。
因此对于N = 4,它应与4
,3 1
,1 3
,2 2
,1 1 1 1
,2 1 1
,{{ 1}},1 2 1
,1 1 2
,似乎您可以对其进行暴力破解,直到您意识到它也必须与1 1 1 1
匹配为止。
4)以同样的方式,我认为您不能使用SI单位分析方程,并验证这些单位在方程的两边是否平衡。例如,“ 10N = 2kg * 5ms ^ -1”。不必介意检查值,只需检查单位是否正确即可。
5)然后,存在所有类别的问题,这些问题是目前计算机程序无法完成的,例如“检查字符串是否正确地用英语区分大小写”,这需要上下文相关的自然语言解析器来正确检测“时间像箭一样飞,但水果像香蕉一样飞”中“赞”的不同含义。