我有一个(php5.2和5.3)正则表达式需要从用户帖子中提取前$ x个句子(可能包括电子邮件地址和超链接),并且我在查找原因时遇到了麻烦(是的,它& #39;是一个丑陋的正则表达式;当它工作时我会优化它):
/^(([^.!?]+|(\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领域,因为它只是网站中的一个功能)是一个句号,感叹号或问号,但句子可以出现在句子中网址的电子邮件地址。这个正则表达式的最后一个版本最多可以计算5个周期,因此会破坏链接和电子邮件地址。
更新3:重申我刚刚添加了更多可怕的代码,我将解释最后一个。发现一些发布的内容有非打印字符(如\ r等),并且与正则表达式不能很好地协作,因此我使用第一个preg_replace删除了非打印字符。第二个用空格替换任何进一步的空格组,所以句子有希望用一个空格分隔。
答案 0 :(得分:0)
正则表达式通过无条件匹配空白字符而结束。如果输入中恰好有5个句子,并且在最后一个句点之后没有空格,则第一个句子匹配,但第二个句子不匹配。
答案 1 :(得分:0)
我认为句子如下:
一句话是:
空格或字符串结尾的要求会处理电子邮件地址中的句点,因为电子邮件地址中的句点不会出现在空格之前或字符串末尾。
/[^ ](?:.*?[.!?]['"]*(?= |\z)){0,4}/
答案 2 :(得分:0)
这个测试过的功能应该可以解决问题:
function get_sentences($text, $x) {
$regex = "/\A(?:.*?[\w\"'][.?!](?=['\"]?\s|\$)){0,{$x}}/ms";
if (preg_match($regex, $text, $matches)) return $matches[0];
return ''; // Never get here (will always match).
}
以下是正则表达式的注释版本:
$regex = '/# Match first $x sentences, each ending in [.?!]
\A # Anchor to beginning of string
(?: # Non-capture group to apply count
.*? # Lazily match zero or more characters.
[\w"\'] # Last char before end is word or quote.
[.?!] # End of sentence puntuation [.?!]
(?=[\'"]?\s|$) # But only if followed by space or EOL
){0,5} # Match from zero to $x sentences.
/smx';
请注意,这也处理以引号结尾的句子,例如: "This one."
或"This one!"
或“这一个”?