PHP正则表达式挑战

时间:2010-11-10 18:19:41

标签: php regex

我对正则表达式的体验不仅仅是介绍,所以这是一个挑战。也许一些数学/物理/有人可以弄清楚......

我们必须用<span class="tooltip"></span>包装某些单词/短语,以便显示跨度内容的相关工具提示。挑战在于如果它是另一个已经被包裹的短语的一部分,如何避免不包装两次单词。

示例:“使用Twitter Analyzer进行分析”。

Twitter和Twitter Analyzer都有工具提示,但只有Twitter Analyzer需要包含在上面。这是通过确保我们首先搜索最长的短语来实现的。

如果两个较短的短语已经被包裹在另一个跨度中,你如何阻止(仅使用正则表达式)两个短短语再次被包裹?

此外,Twitter和Twitter Analytics只是整个列表中的两个示例,因此它必须是通用的。

有什么想法吗?

5 个答案:

答案 0 :(得分:2)

现在,对于强制性,您无法使用正则表达式解析HTML 链接:RegEx match open tags except XHTML self-contained tags

答案 1 :(得分:2)

我认为你最好的选择是匹配你正在寻找的单个短语,并且对于每个匹配,保存匹配开始时的字符串偏移量。构建偏移列表后,将偏移从最低到最高排序。对于列表中的每个偏移量,通过添加字符串长度来计算字符串的结束偏移量。如果列表中的任何后续项目的偏移量小于此新偏移量,请将其删除。如果列表中的两个偏移量相同,则取两个字符串中较长的一个并抛出另一个字符串。

在您给出的示例中,“Twitter Analyzer”的偏移量为4,“Twitter”的偏移量为4。为了演示,请说您对“Analyzer”感兴趣,其偏移量为12。是:

offset 4 - Twitter Analyzer - length 16
offset 4 - Twitter          - length 7
offset 12 - Analyzer        - length 8

因为有两个4,所以抛出一个长度较短的一个。然后将“twitter analyzer”的长度添加到其偏移量中以获得20.任何小于20但大于4的偏移都会被抛出。

要插入字符串,请保留开始和结束偏移列表,并从列表末尾开始。在结束偏移处插入“&lt; / span&gt;”并且在开始偏移时插入“&lt; span class =”tooltip&gt;“在字符串中向后移动直到到达前面。这样您就可以进行替换,而无需重新计算偏移量。

答案 2 :(得分:1)

您不能仅使用 正则表达式执行此操作。正则表达式不能匹配任意数量的平衡开始和结束标记(因为这不构成常规语言)。您需要自己执行计数。

答案 3 :(得分:1)

如果您可以存储要以正则表单形式匹配的列表,则可以使用negative lookahead确保每个匹配都是不同的。您需要访问PCRE functions。一个例子:

$match = array('/Twitter(?! Analyzer)/', '/Twitter Analyzer/');
$replace = '<span class="tooltip">\0</span>';
$output = preg_replace($match, $replace, $input);

我可能不需要提及这会使您的匹配清单更加困难。

答案 4 :(得分:0)

迈克尔提出了一个很好的建议,即使用负向前瞻。那么negative lookbehind呢?

然后你应该逃脱:

$match = '/(?<!\<span class="tooltip">)Twitter/';
$replace = '<span class="tooltip">\0</span>';
$output = preg_replace($match, $replace, $input);

我们不需要维护匹配列表,并且可以在我们浏览单词/短语列表时构建匹配项。不像是什么眼皮说,你会遇到像“Foo Bar”和“Bar Baz”这样的重叠问题。但是,您可以查询找到的匹配项,看看它们是否包含<span class="tooltip"></span>。但不是100%准确。

评论