*注意:Array()的输出是PHP print_r()*
我有这个HTML标记:
<tr>
<td width="40" align="left"><div class="icSkill" id="skill4"></div></td>
<td colspan="2">SOME_VALUE_I_WANT </td>
</tr>
我真的想用RegEx提取它,并且在这种情况下不想使用HTML解析器。
我这样做Regex(我使用s-flag忽略文件的换行符):
\<tr\>\<td\swidth="40"\salign="left"\>\<div\s+class="icSkill"\s+id="skill(\d+)".*\<\/tr\>
现在的问题是正则表达式并没有停留在第一个找到的关闭TR标签,但我想要它。我知道这可能与断言有关,只是我不知道如何。
Array
(
[0] => <tr><td width="40" align="left"><div class="icSkill" id="skill4"></div></td><td colspan="2">SOME_VALUE_I_WANT
</td></tr><tr><td rowspan="2" align="left"><div class="icGuard" id="guard9"></div></td></tr>
[1] => 4
)
基本示例如:/ [^&lt;] * /在这种情况下不起作用。还有一种方法可以告诉正则表达式:
/[^A_STRING]*/ (in words; stop unless you find A_STRING)
OR BETTER EXAMPLE:
/[^A_STRING_FIRST_TIME]*/ (in words; stop unless you find A_STRING for the FIRST_TIME)
答案 0 :(得分:9)
问题是greediness。 .*
消耗尽可能多的消耗。您可以通过附加?
:
~<tr><td\s+width="40"\s+align="left"><div\s+class="icSkill"\s+id="skill(\d+)".*?</tr>~s
另外,正如您所看到的,实际上没有必要进行太多的转义。它只会妨碍易读性。
使重复不成熟的另一种方法是使用修饰符U
,这使得整个模式中的所有重复都不全面。我更喜欢本地变体(使用?
)。
在任何情况下,都有不同的模仿[^A_STRING]*
的可能性(它不起作用,因为它匹配任何字符串,不包括A
,_
, S
,T
,R
,I
,N
或G
)。您可以在重复的每个位置使用negative lookahead:
(?:(?!A_STRING).)*
(将其替换为.*
或.*?
)。在大多数情况下它应该是等效的,但执行时间可能不同。另外,解密起来有点困难。
答案 1 :(得分:1)
这是一个艰难的。通常你会在那里有一个类标识符,这会使它更容易。
因此,让我们确保理解您的需求:在关闭表格行之前,您需要捕获最后<td>
标记内的内容。在这种情况下,您需要一个负向前瞻:
<td(?!.*?<td).*?>(.*?)<\/td>
这与s
修饰符一起捕获SOME_VALUE_I_WANT
,前提是它位于表格行的最后一个<td>
元素中。
这个正则表达式中唯一不直接的元素是负向前瞻操作符<td(?!.*?<td)
,它只捕获一个<td>
元素,后面跟着另一个这样的元素。
此外,当您使用星号运算符时,通常需要确保将其修改为非贪婪,如下所示:(.*?)
。这意味着它会在第一场比赛时停止。