正则表达式返回参考负向前瞻原子组

时间:2012-01-04 10:37:59

标签: php regex atomic lookaround

我希望匹配单引号或双引号,后跟任何不匹配字符的字符数,后跟一个匹配的字符:

"--'__'--"

应该用两端的双引号匹配。但是,我希望这场比赛具有占有欲,因为任何已经过测试的角色都不应该包括在任何未来的比赛中:

"--'__'--

匹配,因为开头的双引号在结尾处从不跟随另一个引号。我想出了:

(?P<q>['"])(?>((?!(?P=q)).)*)(?P=q)

但这仍然与我上面的第二个字符串示例匹配,中间是单引号。我不明白原子团为什么没有做到这一点。我无法通过任何其他原子分组安排来实现这一目标。

此外,如果可以完全匹配引号之间的字符,同时声明引号存在,那将是非常好的。因为lookbehind断言是固定宽度,所以我不能使用后向引用断言所捕获的单引号或双引号组出现在负前瞻之前。

1 个答案:

答案 0 :(得分:0)

假设每行只有一个有效的引用子字符串,这可能是一个很好的起点:

<?php // test.php Rev:20120105_1800
// Return array of valid quoted substrings, one per line.
function getArrayOfOnePerLineValidQuotedSubstrings($text) {
    $re = '%
        # Match line w/1 valid "single" or "double" substring.
        ^               # Anchor to start of line.
        [^\'"]*         # Everything up to first quote.
        (?|             # Branch reset group $1: Contents.
          "([^"]*)"     # Either $1.1 Double quoted,
        | \'([^\']*)\'  # or $1.2 Single quoted contents.
        )               # End $1: branch reset group.
        [^\'"]*         # Everything after quoted sub-string.
        $               # Anchor to end of line.
        %xm';
    if (preg_match_all($re, $text, $matches)) {
        return $matches[1];
    }
    return array();
}
// Fetch test data from file.
$data = file_get_contents('testdata.txt');
// Get array of valid quoted substrings, one per line.
$output = getArrayOfOnePerLineValidQuotedSubstrings($data);
// Display results.
$count = count($output);
printf("%d matches found.\n", $count);
for ($i = 0; $i < $count; ++$i) {
    printf("  match[%d] = {%s}\n", $i + 1, $output[$i]);
}
?>

此正则表达式匹配包含一个有效的引用子字符串的每一行,并跳过具有无效的行(即"--'__'--具有不平衡的双引号子字符串)或没有引用的子字符串。对于匹配的行,有效的引用子字符串的内容将在组$1中返回。该函数返回匹配的子串的数组。

如果您的数据每行包含多个子字符串,或者引用的子字符串或引用的子字符串之间的内容可能包含转义引号,则可能会制定更复杂的解决方案。