【问题标题】:What can NOT be described by a PCRE regex?PCRE 正则表达式不能描述什么?
【发布时间】:2016-02-17 06:54:55
【问题描述】:

我使用了很多正则表达式,但偶然发现了一个正则表达式实际上不能描述的问题。

我想到的第一个例子是匹配像XOOXXXOOOOXXXXX... 这样的字符串。这将是一个由 XO 的交替序列组成的字符串,其中每个子部分仅包含字符 XO 比另一个字符的先前序列长。

谁能解释正则表达式的正式限制是什么?我知道这可能是一个相当学术的问题,但我是一个好奇的人 ;-)

编辑 因为我是一个 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";
}

【问题讨论】:

  • 您还应该定义您希望定义术语“正则表达式”的严格程度 - 现代正则表达式引擎具有使它们能够感知上下文并支持递归的功能; “真正的”正则表达式不能做的两件事。
  • 你是对的。我会更新我的问题。
  • 您一定对 PCRE 与其他正则表达式相比不能做什么感兴趣,或者只是对它不能做什么感兴趣?我看不出有什么实际意义:正则表达式是一种文本解析器,所以它不能递增数字,它不知道对象是否为空等等。你的意思是你想要一个 字符串模式列表 i> 不能与 PCRE 匹配? N 个退格后跟 N 个字符无法删除,但 N 个退格后跟 N 个相同字符是可以删除的。
  • 寻找一个简单而全面的例子来说明 PCRE 无法匹配的内容。演示“正常”正则表达式无法匹配的“标准示例”似乎是平衡的括号系列,但可以通过 PCRE 匹配。只是寻找一个场景,我可以对尝试匹配但无法使用 PCRE 匹配的序列进行口头描述。例如,例如匹配所有素数的 PCRE 不会很令人满意,因为没有人可以真实描述这些字符串的外观。
  • 学术上的答案是正则表达式不能匹配“不规则”语言,尽管在​​实践中有些可以(扩展正则表达式),实际上它们'经常用来做那个(用正则表达式“解析”HTML,不寒而栗)......

标签: php regex pcre computation-theory


【解决方案1】:

我想到的第一个例子是匹配像XOOXXXOOOOXXXXX... 这样的字符串。这将是一个由 XO 的交替序列组成的字符串,其中每个子部分仅包含字符 XO 比另一个字符的先前序列长。

是的,可以这样做。


  1. 要匹配一个非空的 x 序列,后跟更多数量的 o,我们可以使用类似于平衡括号正则表达式的方法:

    (x(?1)?o)o+
    
  2. 为了匹配一个 x 和 o 的字符串,使得任何 x 序列后跟一个更长的 o 序列(除了可选地在最后),我们可以在模式 #1 的基础上进行构建:

    ^o*(?:(x(?1)?o)o+)*x*$
    
  3. 当然,我们还需要模式 #2 的变体,其中 x 和 o 翻转:

    ^x*(?:(o(?1)?x)x+)*o*$
    
  4. 要匹配满足上述两个条件的 x 和 o 字符串,我们可以将模式 #2 转换为正向前瞻断言,并在模式 #3 中重新编号捕获组:

    ^(?=o*(?:(x(?1)?o)o+)*x*$)x*(?:(o(?2)?x)x+)*o*$
    

至于主要问题。 . .我相信 PCRE 可以匹配任何上下文无关语言,因为对第 n 个捕获组的(?<i>n</i>) outside 的支持意味着您基本上可以创建每个非终端的子程序。例如,这种上下文无关文法:

  • SaTb
  • S → ε
  • TcSd
  • TeTf

可以写成:

  • 捕获组 #1 (S) → (a(?2)b|)
  • 捕获组 #2 (T) → (c(?1)d|e(?2)f)

要将其组装成一个正则表达式,我们可以将它们全部连接起来,但毕竟附加{0},但开始非终端,然后添加^$

^(a(?2)b|)(c(?1)d|e(?2)f){0}$

但正如您从第一个示例中看到的,PCRE 也可以匹配一些非上下文无关语言。 (另一个例子是 anbncn,这是一个非上下文无关语言的经典例子。你可以将它与 PCRE 结合起来,为 anbncm 带有 PCRE 用于 ambncn 使用前瞻断言。虽然相交两种正则语言的交集一定是正则的,两种上下文无关语言的交集不一定上下文无关的;但是两个PCRE定义的语言的交集可以被定义通过 PCRE。)

【讨论】:

  • 我想知道您是否知道 PCRE 如何删除与它们后面的退格数相同数量的任何字符。 str = "\bNewqaz\b\b\b car!!!\b\b\b." -> str = "New car." 也许,几个月前我忽略了一些事情:)
  • @WiktorStribiżew:\b 开头的str 去哪儿了?
  • @WiktorStribiżew:如果 \b 只是一个错误,那么 - 您可以使用正则表达式 ([^\b](?1)*[\b]) 匹配(并因此替换)非退格字符和退格字符的平衡对.
  • 感谢您的解释并为^(?=o*(?:(x(?1)*o)o)*x*$)x*(?:(o(?2)*x)x)*o*$ 正则表达式点赞;-)
  • 您应该使用(?(DEFINE)...) 而不是(...){0} 来,嗯...*定义*规则 - 这正是它的用途。见here
【解决方案2】:

可以被正则表达式识别的所有语言的集合被称为“regular languages”,这并不奇怪。

接下来最复杂的语言是context-free languages。它们不能被任何正则表达式解析。标准示例是“所有平衡括号”——所以是“()()”和“(())”,但不是“(()”。

上下文无关语言的另一个很好的例子是 HTML。

【讨论】:

  • ^((?:\((?1)*\))*)$ in PCRE matches balanced parentheses.
  • FTFA:“正则语言是一种可以使用正则表达式表达的形式语言,在理论计算机科学中使用的后者概念的严格意义上(与许多正则表达式相反现代编程语言提供的引擎,这些引擎增加了一些功能,可以识别经典正则表达式无法表达的语言)。”
  • 我知道。 OP 不是在询问正式的正则表达式,而是在询问 PCRE。在我问他(以及你的回答之后)之后,他澄清了这一点。
  • 是的,问题很明确,但我不知道(也无法在网上找到)PCRE 可能对语言进行的任何正式分析。
【解决方案3】:

我没有确凿的证据表明使用递归、平衡组、自引用组和将文本附加到正在测试的字符串等任何事情都是不可能的。我很高兴在任何或所有这些方面都被证明是错误的,因为我会学到一些东西!

  1. 数学很差。

例如,我不相信使用 PCRE 来检测升序的数字序列是可能的:也就是说,匹配“1 2 7 97 315 316...”而不是“127 97 315 316。 ..”

  1. 我不确定是否可以匹配一个序列从 1 连续增加, 如“1 2 3...”,而无需详尽列出所有可能性,如 /1( 2( 3(...)?)?)?/ 直到最大值您要检查的长度。

您可以通过将已知文本添加到待测字符串来使其工作(例如,http://www.rexegg.com/regex-trick-line-numbers.html 通过在文件末尾添加一系列数字来工作)。但作为原始正则表达式,简单的数学只能通过暴力破解。

  1. 我认为它会失败的另一个示例是“匹配任何总和为 N 的序列”。

所以对于 N=4,它应该匹配 43 11 32 21 1 1 12 1 11 2 11 1 21 1 1 1,看起来就像你可以蛮力一样,直到你意识到它也必须匹配4 -12 11 0 1

  1. 以同样的方式,我认为你不能让它使用 SI 单位分析方程,并验证方程两边的单位是否平衡。例如,“10N=2kg*5ms^-1”。没关系检查值,检查单位是否正确。

  2. 然后是目前没有计算机程序可以解决的所有问题,例如“检查一个字符串是否正确地用英文标题大小写”,这需要一个上下文相关的自然语言解析器来正确检测不同的《时光如箭,果如香蕉》中的“喜欢”。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-09-28
    • 1970-01-01
    • 1970-01-01
    • 2023-03-20
    • 2014-08-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多