【问题标题】:regex back reference negative lookahead atomic group正则表达式反向引用负前瞻原子组
【发布时间】:2012-01-04 10:37:58
【问题描述】:

我想匹配一个单引号或双引号,后跟任意数量的不是刚刚匹配的字符,然后是匹配的字符之一:

"--'__'--"

应该匹配两端的双引号。但是,我希望匹配具有所有格,因为任何已经测试过的字符都不应该包含在任何未来的匹配中:

"--'__'--

应该 匹配,因为开头的双引号永远不会在末尾跟随另一个。我想出了:

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

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

另外,如果在断言引号存在的同时仅匹配引号之间的字符是可能的,那就太好了。因为后向断言是固定宽度的,所以我不能使用反向引用来断言捕获的单引号或双引号组发生在负前瞻之前。

【问题讨论】:

  • 您的输入是否仅由这些组成,还是还有其他内容?你的正则表达式没有锚定是有原因的吗?
  • @fge 好点。除非我最终将所有内容分解为更小的子表达式,否则这可能会成为更大表达式的一部分。我没有过多地使用正则表达式,我不太确定我将如何在这里使用锚点。开始锚会确保它不会像我的第二个字符串那样“在中间匹配”吗?如果这个表达式在输入开始时不匹配,那会如何改变?
  • 好吧,行锚的开头确保了匹配确实只能出现在开头。您可以尝试在开头添加^ 看看它的行为吗?
  • 我有这个有效的正则表达式:'^(['"])(((?!\1).)+)\1$' + 替换为++
  • 好的...所以似乎阻止它匹配'_'"-'_'- 的唯一方法是使用起始锚点?如果是这样,我将不得不根据其他标准分割输入以在字符串的开头使用这个子集。关于原子组,如果我错了,请纠正我-根据我的研究,我认为(?&gt;expression*) 应该等同于expression*+?我认为原子组符号是首选。

标签: php regex atomic lookaround


【解决方案1】:

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

<?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 中返回。该函数返回一个匹配的子字符串数组。

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

【讨论】:

    猜你喜欢
    • 2011-02-27
    • 2021-10-11
    • 2011-10-14
    • 2010-12-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多