PHP预匹配组重复

PHP预匹配组重复,php,regex,preg-match,Php,Regex,Preg Match,我有一个(php5.2和5.3)正则表达式,需要从用户帖子(可能包括电子邮件地址和超链接)中提取第一个$x句子,但我很难找出原因(是的,这是一个丑陋的正则表达式;我会在它起作用时对其进行优化): 返回前四个句子,但是 /^(([^.!?]+|(\w+[.@?&=%:])+\w+)+[.!?]+\s){0,5}/ 不返回匹配项。我的理解是,{0,5}应该在0到5次之间匹配前一个组,因此如果它只能匹配它4次,它仍然可以工作 有人能解释一下这种行为吗 更新:$x只是一个任意数字;在正则表达式

我有一个(php5.2和5.3)正则表达式,需要从用户帖子(可能包括电子邮件地址和超链接)中提取第一个$x句子,但我很难找出原因(是的,这是一个丑陋的正则表达式;我会在它起作用时对其进行优化):

返回前四个句子,但是

/^(([^.!?]+|(\w+[.@?&=%:])+\w+)+[.!?]+\s){0,5}/
不返回匹配项。我的理解是,{0,5}应该在0到5次之间匹配前一个组,因此如果它只能匹配它4次,它仍然可以工作

有人能解释一下这种行为吗

更新:$x只是一个任意数字;在正则表达式中使用{0,$x}。帖子被过滤成由单个空格分隔的句子。对不起,我的表情很难看。。。这件事我已经调查了好几天了,现在我的脑子都在想。。。进行了sawa建议的更改。我的主要问题是关于行为,以及小组比赛的内容不应该那么重要

更新2:这基本上就是我正在做的:

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_替换删除了非打印字符。第二个用一个空格替换任何进一步的空格组,因此句子希望只被一个空格分隔。

正则表达式以无条件匹配一个空格字符结束。如果输入中正好有5个句子,并且在最后一个句点后没有空格,第一个将匹配,但第二个将不匹配。

我识别的句子如下:

一句话是:

  • 最短的句号、感叹号或问号
  • (可选)后跟单引号或双引号
  • 后面紧跟空格或字符串的结尾
空格或字符串结尾的要求考虑电子邮件地址中的句点,因为电子邮件地址中的句点不会出现在空格之前或字符串末尾

/[^ ](?:.*?[.!?]['"]*(?= |\z)){0,4}/

此已测试函数应实现以下功能:

函数获取句子($text,$x){
$regex=“/\A(?:*?[\w\“'][.?!](?=['\“]?\s\$){0,{$x}}/ms”;
if(preg_match($regex,$text,$matches))返回$matches[0];
返回“”;//从未到达此处(将始终匹配)。
}
以下是正则表达式的注释版本:

$regex='/#匹配前$x个句子,每个句子以[.?!]结尾
\锚定到弦的开头
(?:#要应用计数的非捕获组
*?#延迟匹配零个或多个字符。
[\w“\']”结尾前的最后一个字符是单词或引号。
[.?!]#句末押韵[.?!]
(?=[\'”]?\s |$)#但仅当后跟空格或EOL时
){0,5}#匹配从零到$x的句子。
/smx’;

请注意,这也处理以引号结尾的句子,例如
“this one.”
“this one!”
或“this one”?

什么是$x句子?post是什么样的?在这样做之前,您应该清理正则表达式。例如,您不需要
中最外面的一对括号((\w+[…\w)
,您在捕获方面并不一致:有时您有
(…)
,而有时您有
(?:…)
。仅当您想提取该部分时才使用前者。我认为仅仅发布一个复杂的正则表达式并让人们遵循它是不礼貌的。感谢您遵循建议,但我认为一些例句是必要的,或者至少您应该告诉我们您作为一个句子的想法。一个句子仅仅是一个句点之前的序列吗?根据你所拥有的推测,情况可能并非如此。只有当句号是电子邮件地址的一部分时,才允许在一个句子中使用句号吗?定义一个句子的条件是什么?这并不能解释为什么它在第一个正则表达式中成功,而在第二个正则表达式中失败,正如Rodney所说。文章在结尾处插入了空格,在前面它在正则表达式中运行,以避免出现这种情况。这会导致不匹配,即使在基本情况下也是如此。尝试使用“这是一个句子。这是句子2。这个句子有一封电子邮件。address@domain.com.这有一个链接。这句话不应该出现在输出中。“是的,两个都试过了。更新之前,结果不是不匹配,但匹配是一个空字符串。这在正则表达式中是有意义的,但不是我想要的-我需要提取句子,而不是测试匹配。这只提取第一个句子。只需稍加修改,它就会得到前4个句子:/(*?[!?])(?=\s)){0,4}/”,但当它遇到电子邮件地址或链接时仍然会中断。不处理以引号结尾的句子,例如像“这一个”这样的
他说:“它不起作用!”
我在哪里添加引号的问题上出错。我修复了它,编辑了整个答案。很好,但在包含链接的句子之前停止输出:例如“这是第一句,这是第二句,这是someone@somewhere.com三、“仅输出”这是第一句。这是第二句。“即使$x>2。@罗德尼:不。这对你的例子来说效果很好,结尾的标点符号后面必须跟空格或行尾。我的错误,输入了你的表达式。效果很好。谢谢!
/[^ ](?:.*?[.!?]['"]*(?= |\z)){0,4}/