RegEx用于匹配模式嵌套

时间:2019-05-01 18:36:03

标签: php regex preg-match

我需要检测一个标签在另一个标签中的嵌套以引发错误。

示例:

anything <amb id="1">word1</amb> anything <amb id="2">word2</amb> anything // OK

anything <amb id="1">anything<amb id="2">word2</amb>anything</amb> anything // KO

因此有必要检测标签<amb...</amb>之间的标签<amb...</amb>

我有一个模式的开始,但是我无法管理标签的嵌套状态。

// #\<amb(.*?)\<\/amb\># => OK : detect the first level
$pattern = '#\<amb(?!\<amb)\<\/amb\>#'; // KO

if(preg_match($pattern, $string)) {
  throw new Exception('No nested tags are allowed.');
}

我该如何解决这个问题?

2 个答案:

答案 0 :(得分:3)

检查标签嵌套的一种方法是检查是否出现了两个连续的<amb标签,而中间没有</amb>标签,那么您可以拒绝表示标签嵌套的字符串。这种基于负面展望的正则表达式应该可以胜任工作,

^(?!.*<amb(?:(?!<\/amb).)+<amb).+$

Regex Demo 1

类似地,另一种方法是检查两个连续的<\/amb>标签是否出现而中间没有<amb标签,这意味着标签是嵌套的,并且可以再次使用此否定的外观拒绝字符串基于正则表达式,

^(?!.*<\/amb>(?:(?!<amb).)+<\/amb>).+$

Regex Demo 2

让我知道这是否对您有用。

答案 1 :(得分:1)

您不需要正则表达式。 They are a pain。您可以做的是炸开</amd>上的字符串,然后检查每个部分中最多包含一个<amb。像这样:

function correctlyNested($html, $tag)
{
    foreach (explode("</$tag>", strtolower($html)) as $part) {
       if (substr_count($part, "<$tag") > 1) return false; // it is KO
    }
    return true; // it is OK
}


$tests = ['anything <amb id="1">word1</amb> anything <amb id="2">word2</amb> anything',
          'anything <amb id="1">anything<amb id="2">word2</amb>anything</amb> anything'];

foreach ($tests as $test) {
    echo $test . (correctlyNested($test, "amb") ? " // OK<br>" : " // KO<br>");
}

此代码易于理解和维护。我添加了strtolower(),以说明扩展此代码有多么容易。