Regex,从html编码字符串中提取单个值


Regex, extract single value from html encoded string

我在提取一些值时遇到了麻烦,下面是我的表达式:

flag:('S+)='&quot';?((?:.(?!'&quot?'s+(?:'S+)=|">))+.)'&quot';?

它只是试图从html编码的字符串中提取值。

下面是一个很好的例子。

<p class="text1" target="701_text" flag:text1="This is a test">

为第二次()捕获返回此值,这是正确的:This is a test

然而,单个值似乎返回第一个字符,加上第一个";

<p class="text1" target="701_text" flag:text1="T">

返回:;T而不是T,这是我需要它做的。

我只需要修改表达式,以允许单个值,同时仍然正确返回多个值

我想这就是你想要的正则表达式:

flag:('S+)="((?:.(?!"(?:'S+)=|">))*.?)"

注意,您不需要转义那么多。&;不是特殊字符,因此不需要转义。此外,HTML实体总是以分号结束,否则它们是无效的,因此在;之后的所有问号都是不需要的(或相当有害)。

那么你的表达式的实际问题如下:对"具有负面前瞻性的内部组期望有1个或多个匹配(因为+)。在T作为单个文本的情况下,T已经被之后的.占用(这是正确的要求,以匹配应用负正向查找的最后一个字符)。现在没有剩下的字符来实际匹配前瞻性表达式(尽管这需要一个匹配)。那么regexp做了什么呢?它使用标记为可选的分号(因为?)并将其拉到捕获组中。这就解释了分号的来源。

如果您按照上面的建议删除分号后面的问号,那么您就会遇到regexp根本不匹配T的问题(因为它需要两个或更多字符)。因此,解决方案是不允许任何字符匹配负前瞻性表达式(即*而不是+)。然后,如果您想使regexp更好,也可以通过在最后的.中添加?来允许引号内的空序列。然后你应该有一个工作表达式。

但是,当然,考虑到这是使用HTML实体编码的,它可能是一个更好的主意,简单地解码那些,然后直接匹配引号,正如Matteo建议的那样。这个答案仅仅是为了解释你的表达式出了什么问题:)

为什么不先解码然后处理那个版本的字符串呢?如果我理解你的要求,你可以试试这个:

$str = '<p class="text1" target="701_text" flag:text1="T">';
$decoded = html_entity_decode($str);
preg_match('/flag:(.+?)="(.+?)"/', $decoded, $match);
print_r($match);