用于匹配模式嵌套的正则表达式

RegEx for matching schema nesting

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

示例:

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.');
}

如何解决这个问题?

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

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

Regex Demo 1

同样,另一种方法是检查两个连续的 <\/amb> 标签是否出现,中间没有 <amb 标签,这意味着标签是嵌套的,你可以再次使用这个否定来拒绝字符串向前看基于正则表达式,

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

Regex Demo 2

让我知道这是否适合你。

您不需要为此使用正则表达式。 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() 以显示扩展此代码有多么容易。