有没有一个PHP代码片段可以提取字符串中的第一个“句子”?

12
如果我有一个描述,例如:

"我们更喜欢可以回答的问题,而不只是讨论。提供详细信息。明确简洁地写下来。"

如果我只想要:

"我们更喜欢可以回答的问题,而不只是讨论。"

我会搜索一个正则表达式,比如 "[.!\?]",确定它在主字符串中的位置,然后从主字符串中提取子字符串。但我认为这是一种常见的操作,希望有人能提供代码片段。

这是一个真正困难的问题。如果您需要强大的结果,我建议研究自然语言处理包。分词器可以识别句子结束字符(根据您的预期使用,可以是“?”,“。”,“;”等),然后您可以在此基础上进行拆分。 - Kevin Peterson
7个回答

23

如果你想选择多种标点符号作为句子终止符,稍微花费更多的表达式会更具适应性。

$sentence = preg_replace('/([^?!.]*.).*/', '\\1', $string);

查找跟随空格的终止字符

$sentence = preg_replace('/(.*?[?!.](?=\s|$)).*/', '\\1', $string);

你一定是在我修改代码之前就已经拿到了它 :) 如果你再看一遍,那就是我发布的内容。 - Ian Elliott
我们更喜欢低于7.50美元的价格。如果价格太高,我们就不会购买了。 - dyve
顺便说一句,仅仅添加\s对我没有起作用(见上文)。谢谢大家,这是一个有用的片段。 - FilmJ
1
这个正则表达式如果句号后面是换行符而不是空格就会失败。你可能需要先通过 preg_replace('/\s+/', ' ', $text); 运行它。 - Nick
你必须使用s修饰符。例如:'/^(.*?[?!.])(\s|$).*/s' - gphilip
显示剩余8条评论

8
<?php
$text = "We prefer questions that can be answered, not just discussed. Provide details. Write clearly and simply.";
$array = explode('.',$text);
$text = $array[0];
?>

需要注意的是,这种方法会在所有“.”(即句号)处出现问题而导致程序崩溃。因此,如果句子中包含缩写词,例如“i.e.”或“e.g.”,则会遇到问题。除此之外,这是最简单的选择。 - mdec
然而,并非所有的句子都以“.”结尾。我需要处理“!”和“?”的东西,所以它可能需要使用正则表达式。 - FilmJ
你可以通过'!','?'等进一步分割$array的元素。 - Jason
但是您无法动态选择要拆分的内容。 - Ian Elliott

5

我的上一个正则表达式在测试工具中似乎是有效的,但在实际的PHP中却不起作用。我已经编辑了这个答案,提供完整且可用的PHP代码以及改进后的正则表达式。

$string = 'A simple test!';
var_dump(get_first_sentence($string));

$string = 'A simple test without a character to end the sentence';
var_dump(get_first_sentence($string));

$string = '... But what about me?';
var_dump(get_first_sentence($string));

$string = 'We at StackOverflow.com prefer prices below US$ 7.50. Really, we do.';
var_dump(get_first_sentence($string));

$string = 'This will probably break after this pause .... or won\'t it?';
var_dump(get_first_sentence($string));

function get_first_sentence($string) {
    $array = preg_split('/(^.*\w+.*[\.\?!][\s])/', $string, -1, PREG_SPLIT_DELIM_CAPTURE);
    // You might want to count() but I chose not to, just add   
    return trim($array[0] . $array[1]);
}

这似乎实际上不起作用。你自从第一次发布以来改变了它吗? - FilmJ
所以这不仅现在可以工作,而且最终实际处理了我的现实问题,而Ian的解决方案则没有...(虽然刚开始时它确实可以)。正如我在上面评论中所述,也许这是因为结果是Unicode字符串...不确定,但值得思考。感谢这个函数-我肯定会再次使用它。 - FilmJ
只是想指出,你需要在preg_split模式中添加/m,以使其能够处理多行句子。 - Kalamun

3

试试这个:

$content = "My name is Younas. I live on the pakistan. My email is **fromyounas@gmail.com** and skype name is "**fromyounas**". I loved to work in **IOS development** and website development . ";

$dot = ".";

//find first dot position     

$position = stripos ($content, $dot); 

//if there's a dot in our soruce text do

if($position) { 

    //prepare offset

    $offset = $position + 1; 

    //find second dot using offset

    $position2 = stripos ($content, $dot, $offset); 

    $result = substr($content, 0, $position2);

   //add a dot

   echo $result . '.'; 

}

输出结果为:

我叫Younas。我住在巴基斯坦。


0
current(explode(".",$input));

0
我可能会使用PHP中的任何子字符串/字符串拆分函数(已经有一些在这里提到了)。 但是也要寻找“. ”或“。\n”(可能还有“。\n\r”),而不仅仅是“。”。以防万一,句子包含一个没有后面跟着空格的句号。我认为这将增加您获得真实结果的可能性。
例如,在以下内容中搜索“。”:
"I like stackoverflow.com."

会得到:

"I like stackoverflow."

实际上,我相信你更喜欢:

"I like stackoverflow.com."

一旦你有了基本的搜索功能,可能会出现一两个遗漏的情况。在运行时进行调整!


大多数字符串可能不会在其内部包含换行符。 - Ian Elliott
我认为许多字符串(包括我项目中的一些)将具有URL...因此找出解决方案对于这个问题很重要,尽管上面所接受的答案暂时还不错。 - FilmJ

0

试试这个:

reset(explode('.', $s, 2));

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接