【发布时间】:2010-08-27 15:43:45
【问题描述】:
我正在尝试找到一个优化的正则表达式来返回围绕另一个单词的 N 个单词(如果可用)以构建摘要。该字符串采用 UTF-8 格式,因此“单词”的定义不仅仅是 [a-z]。用作参考词的字符串可以在词的中间,也可以不直接被空格包围。
我已经得到了以下有效的方法,但在寻找超过 6-7 个单词时看起来实际上很贪婪和窒息:
/(?:[^\s\r\n]+[\s\r\n]+[^\s\r\n]*){0,4}lorem(?:[^\s\r\n]*[\s\r\n]+[^\s\r\n]+){0,4}/u
这是我为此构建的 PHP 方法,但我需要帮助让正则表达式不那么贪婪,并且可以处理任意数量的单词。
/**
* Finds N words around a specified word in a string.
*
* @param string $string The complete string to look in.
* @param string $find The string to look for.
* @param integer $before The number of words to look for before $find.
* @param integer $after The number of words to look for after $find.
* @return mixed False if $find was not found and all the words around otherwise.
*/
private function getWordsAround($string, $find, $before, $after)
{
$matches = array();
$find = preg_quote($find);
$regex = '(?:[^\s\r\n]+[\s\r\n]+[^\s\r\n]*){0,' . (int)$before . '}' .
$find . '(?:[^\s\r\n]*[\s\r\n]+[^\s\r\n]+){0,' . (int)$after . '}';
if (preg_match("/$regex/u", $string, $matches)) {
return $matches[0];
} else {
return false;
}
}
如果我有以下 $string:
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras auctor,
felis non vehicula suscipit, enim quam adipiscing turpis, eget rutrum
eros velit non enim. Sed commodo cursus vulputate. Aliquam id diam sed arcu
fringilla venenatis. Cras vitae ante ut tellus malesuada convallis. Vivamus
luctus ante vel ligula eleifend condimentum. Donec a vulputate velit.
Suspendisse velit risus, volutpat at dapibus vitae, viverra vel nulla."
并调用getWordsAround($string, 'vitae', 8, 8) 我想得到以下结果:
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras auctor,
felis non vehicula suscipit,"
感谢您的帮助正则表达式专家。
【问题讨论】:
-
对于初学者来说,
\s包括\r和\n,因此将它们添加到相同的字符类是多余的。同样[^\s]等价于\S -
提示,感谢 NullUserException。
-
顺便说一句,这是一个有趣的问题。当我回来时,我会尝试提出更好的解决方案。 +1
-
@NullUserException 谢谢!我也玩得很开心。如果您找到更好的解决方案,请告诉我,与此同时,我会看看我是否也能想出一些办法,我从下面的内容中得到了一些不错的想法。