正则表达式,从html编码的字符串中提取单个值

时间:2011-11-08 21:28:51

标签: php regex

我无法提取某些值,这是我的表达式:

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

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

这是一个工作正常的例子。

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

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

但是,单个值似乎会返回第一个字符,加上第一个;的{​​{1}}

"

返回:<p class="text1" target="701_text" flag:text1="T">而非;T,这是我需要它做的。

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

2 个答案:

答案 0 :(得分:1)

为什么不首先解码它并处理该字符串的版本?如果我理解您的要求,您可以尝试这样做:

$str = '<p class="text1" target="701_text" flag:text1="T">';

$decoded = html_entity_decode($str);

preg_match('/flag:(.+?)="(.+?)"/', $decoded, $match);

print_r($match);

答案 1 :(得分:1)

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

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

请注意,您无需逃避这么多。 &;不是特殊字符,因此不需要转义。此外,HTML实体始终以分号结尾,或者它们无效,因此;之后的所有问号都不需要(或者更有害)。

然后,表达式的实际问题如下:"具有负前瞻的内部组预期有一个或多个匹配(因为+)。如果T作为单个文本,T之后.已经占用{正确需要匹配负前瞻适用的最后一个字符)。现在没有任何字符可以实际匹配前瞻表达式(虽然需要一个匹配)。那么正则表达式做了什么呢?将分号标记为可选(因为?)并将其拉入捕获组内部。这就解释了分号的来源。

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

但是,当然,鉴于这是使用HTML实体进行编码,最好先简单解码,然后直接在引号上进行匹配,如Matteo所建议的那样。这个答案仅仅是为了解释你的表达方式有什么问题:)