0

我试图找出一个 preg_match / php 样式的正则表达式来查找重复的字母数字字符组(任何长度),用逗号分隔?

所以如果我有字符串 "c,b,a,xz,x,b,a,c,xz,x,x,b,a"

将返回重复两个以上值的第一系列字母。我想我需要做一个递归反向引用,也许像

<?php
    // lines removed for simplicity
    // test string = "c,b,a,xz,x,b,a,c,xz,x,x,b,a"
    $haystack = "c,b,a,xz,x,b,a,c,xz,x,x,b,a";
    $answer = preg_match('/([A-z]{2,*}[\s]{1})([A-z \s]*)[\1]*/', $haystack );

    echo $answer; // print the first occurrence of the repeating series of two or more
?>

我只需要找到并回显重复的两个或多个值系列的第一次出现。有没有办法递归地使用反向引用,或者更好的方法?

编辑:删除代码呕吐物。

4

2 回答 2

1

'/\b(\w+,\w+),(?:.*,)?\1\b/'应该管用。它会匹配任何两个项目的序列,任何数量的其他东西,然后再次匹配相同的序列。

关键是,由于正则表达式的工作方式,它可能会找到第一个重复的序列,而不是第一个重复的序列。(最早开始的比赛获胜。)例如,如果你有'a,b,c,d,c,d,a,b,c'$matches[1]可能会是'a,b',即使'c,d'会更早匹配。

要找到第一个重复项,您必须能够匹配它并在后向断言中对其进行反向引用。如果这甚至是合法的(我怀疑它是合法的),它必须是固定的宽度,然后 PHP 才会让它发生。

编辑: 虽然,现在我考虑了一下......如果你反转字符串然后使用'/.*\b(\w+,\w+),(?:.*?,)??\1\b/'它,它可能会起作用。这围绕着我提到的约束跳舞;将字符串颠倒后,副本出现原始字符串之前,所以现在我们可以匹配副本,然后“稍后”引用它。

表达式的.*开头尽可能多地抓取,因此匹配将尽可能靠近反转字符串的结尾(因此,尽可能靠近原始字符串的开头)。并且额外?的 s 使它们相应的位变得惰性,因此它们尽可能少地匹配。当然,一旦在反转字符串中找到匹配项,您需要反转它才能在原始字符串中获得匹配项。

当然,在 UTF-8 存在的情况下,这可能会彻底崩溃。(再说一次,大多数正则表达式都会。)但是,如果您只是在处理 ASCII,它应该可以工作。

于 2012-04-20T02:09:46.190 回答
1

不是 PHP 专家,但我认为您可以
~\b([a-zA-Z0-9]{2,})\b(?=.*\b\1\b)~在 while 循环中使用此正则表达式。

在正文中,您可以在哈希数组中跟踪结果(如果 php 有),
以打印出唯一的系列和位置。捕获缓冲区 1 具有系列。

于 2012-04-20T04:34:01.833 回答