【发布时间】:2011-03-29 01:30:14
【问题描述】:
我有一个(php5.2 和 5.3)正则表达式,它需要从用户帖子(可能包括电子邮件地址和超链接)中提取前 $x 个句子,并且在试图找出原因时遇到了麻烦(是的,它是一个丑陋的正则表达式;我会在它工作时对其进行优化):
/^(([^.!?]+|(\w+[.@?&=%:])+\w+)+[.!?]+\s){0,4}/
返回前四个句子,但是
/^(([^.!?]+|(\w+[.@?&=%:])+\w+)+[.!?]+\s){0,5}/
不返回任何匹配项。我的理解是 {0,5} 应该匹配前一个组 0 到 5 次,因此如果它只能匹配它 4 次,它应该仍然有效。
谁能解释一下这种行为?
更新:$x 只是一个任意数字;在正则表达式中使用 {0,$x}。帖子被过滤为由单个空格分隔的句子。对不起,丑陋的表情......现在已经研究了几天,它让我很头疼......做出了sawa建议的改变。我的主要问题是关于行为,组匹配的内容应该没有那么重要。
Update2:这基本上就是我正在做的事情:
function extractSummary($message, $limit) {
$expr = '/^(([^.!?]+|(\w+[.@?&=%:])+\w+)+[.!?]+\s){0,'.$limit.'}/';
$msg = preg_replace('/[\x00-\x1f\x80-\xff]/', "\n" strip_tags($message));
$msg = trim(preg_replace('/(\n|\s| )+/', ' ', $msg)).' ';
preg_match($expr, $msg, $summary);
return $summary[0];
}
一个句子(至少在我看来,没有进入 NLP 领域,因为它只是用于站点中的一个功能)是任何不超过句点、感叹号或问号的东西,但句点可以出现在句子中的URL 的电子邮件地址。这个正则表达式的最后一个版本最多只计算了 5 个句点,因此在链接和电子邮件地址上中断了。
更新 3:意识到我刚刚添加了更可怕的代码,我将解释最后一个。一些发布的内容被发现有非打印字符(如 \r 等)与正则表达式不能很好地配合,所以我用第一个 preg_replace 删除了非打印字符。第二个用一个空格替换任何进一步的空白组,因此希望句子之间正好用一个空格分隔。
【问题讨论】:
-
什么是 $x 句?帖子怎么样?
-
在此之前,您应该清理您的正则表达式。例如,您不需要
((\w+[....\w)中最外面的一对括号,并且您在捕获方面不一致:有时您有(...),而有时您有(?:...)。仅当您要提取该部分时才使用前者。我认为仅仅发布一个复杂的正则表达式并让人们遵循它是不礼貌的。 -
感谢您的建议,但我认为一些例句是必要的,或者至少您应该告诉我们您的想法。一个句子只是一个句号的序列吗?从你所拥有的推测,情况可能并非如此。只有当它是电子邮件地址的一部分时,才允许在句子中使用句点?定义句子的条件是什么?
标签: php regex preg-match