5

*注意: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&nbsp;</td>
</tr>

我真的很想用 RegEx 提取它,并且不想在这种情况下使用 HTML 解析器。

我做这个正则表达式(我使用 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&nbsp;
</td></tr><tr><td rowspan="2" align="left"><div class="icGuard" id="guard9"></div></td></tr>
    [1] => 4
)

像这样的基本示例: /[^<]*/ 在这种情况下不起作用。还有一种方法可以告诉正则表达式,例如:

/[^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)
4

2 回答 2

9

问题是贪婪.*尽可能多地消耗。您可以通过附加以下内容使其变得不贪婪?

~<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的字符串)。您可以在重复的每个位置使用负前瞻:NG

(?:(?!A_STRING).)*

(用这个代替.*or .*?)。在大多数情况下它应该是等效的,但执行时间可能不同。另外,破译有点困难。

于 2012-12-12T14:48:29.233 回答
1

这是困难的一个。通常你会有一个类标识符,这会更容易。

因此,让我们确保我理解您想要什么:您需要<td>在我们关闭表格行之前捕获最后一个标签中的任何内容。在这种情况下,您需要负前瞻:

<td(?!.*?<td).*?>(.*?)<\/td>

这与s修饰符一起将捕获SOME_VALUE_I_WANT&nbsp;,前提是它位于<td>表格行的最后一个元素中。

此正则表达式中唯一不直接的元素是负前瞻运算符<td(?!.*?<td),它将仅捕获一个<td>元素,该元素后面没有另一个此类元素。

此外,当您使用星号运算符时,您通常希望确保将其修改为非贪婪,如下所示(.*?):这意味着它在第一场比赛中停止。

于 2012-12-12T15:34:37.823 回答