我无法提取某些值,这是我的表达式:
flag:(\S+)=\"\;?((?:.(?!\"?\s+(?:\S+)=|">))+.)\"\;?
它只是试图从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
,这是我需要它做的。
我只需要修改表达式以允许单个值,同时仍然可以正确返回多个值。
答案 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所建议的那样。这个答案仅仅是为了解释你的表达方式有什么问题:)