我有一个正则表达式,用于以包含关键字(关键字基于模式,例如{query:ABCD:1234})的方式截断字符串,在关键字之前5个单词,在关键字之后5个单词。然后在该关键字之前和之后,我将显示三个点,例如:
Lorem ipsum dolor sit amet, consectetur {query:ABCD:1234} adipiscing elit. Mauris consequat, quam id feugiat varius.
我希望:
... ipsum dolor sit amet, consectetur {query:ABCD:1234} adipiscing elit. Mauris consequat, quam ...
这里是正则表达式:
preg_match("/((?:\w+\W+){5})" . preg_quote($keyword, "/") . "((?:\W+\w+){5})/", $text, $matches);
问题是当最后一个单词附加到点/问号/感叹号时,此正则表达式不起作用,例如:
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris consequat, quam id feugiat varius {query:ABCD:1234}.
我希望
... quam id feugiat varius {query:ABCD:1234}.
但返回:
... quam id feugiat varius {query:ABCD:1234}
((末尾没有点。)
当最后一个单词不是关键字时也是一样:
Original: {query:ABCD:1234} Lorem ipsum dolor sit amet!
Returns: {query:ABCD:1234} Lorem ipsum dolor sit amet ...
Expected: {query:ABCD:1234} Lorem ipsum dolor sit amet!
如何解决?
更新:
这是我的代码:
function cutMessage($text, $search)
{
$pieces = explode(' ', $text);
$firstWord = $pieces[0];
$lastWord = array_pop($pieces);
preg_match("/((?:\w+\W+){0,5})" . preg_quote($search, "/") . "((?:\W+\w+){0,5})/", $text, $matches);
$returnText = '';
$pieces = explode(' ', $matches[1]);
if (!empty($matches[1]) && $pieces[0] != $firstWord) {
$returnText .= '... ' . $matches[1];
} elseif (!empty($matches[1])) {
$returnText .= $matches[1];
}
$returnText .= $search;
$pieces = explode(' ', $matches[2]);
if (!empty($matches[2]) && array_pop($pieces) != $lastWord) {
$returnText .= $matches[2] . ' ...';
} elseif (!empty($matches[2])) {
$returnText .= $matches[2];
}
return $returnText;
}
如果使用示例关键字回显当前模式,则(?:\W+\w+){0,5}
末尾的该部分与逗号或感叹号不匹配,因为\w+
与1个或多个单词字符匹配。
((?:\w+\W+){0,5})\{query\:ABCD\:1234\}((?:\W+\w+){0,5})
^^
一个选项是将第三个捕获组([!.]?)
中允许匹配的任何非单词字符匹配0倍以上>
((?:\w+\W+){0,5})\{query\:ABCD\:1234\}((?:\W+\w+){0,5})([!.]?) ^^^^^^^
当您检查捕获组的值是否不为空时,您可以为第三捕获组添加另一项检查。
如果该组不为空,则连接组2和组3。
if (!empty($matches[3])) {
$returnText .= $matches[2] . $matches[3];
} elseif (!empty($matches[2]) && array_pop($pieces) != $lastWord) {
$returnText .= $matches[2] . ' ...';
} elseif (!empty($matches[2])) {
$returnText .= $matches[2];
}
return $returnText;