如何从字符串的开头到第二个最后一个点剪切字符串?

时间:2016-06-14 12:06:11

标签: php regex mbstring

我有一些字符串,例如:

cats, e.g. Barsik, are funny. And it is true. So,

我希望得到结果:

cats, e.g. Barsik, are funny.

我的尝试:

mb_ereg_search_init($text, '((?!e\.g\.).)*\.[^\.]');
$match = mb_ereg_search_pos();

但是它获得了第二个点的位置(在#34之后;真的")。

如何获得理想的结果?

2 个答案:

答案 0 :(得分:1)

由于天真的方法适合你,我发布了一个答案。但是,请注意,检测句子结束对于正则表达式来说是一项非常困难的任务,尽管在某种程度上可以使用,但是应该使用NLP包。

话虽如此,我建议使用

'~(?<!\be\.g)\.(?=\s+\p{Lu})~ui'

正则表达式匹配任何前面没有整个单词\.的点(e.g)(请参阅否定的lookbehind (?<!\be\.g)),但后面跟着一个或多个空格( \s+)后面跟着1个大写的Unicode字母\p{Lu}

请参阅regex demo

不区分大小写的i修饰符不会影响\p{Lu}匹配的内容。

由于您使用的是Unicode文本(如俄语),因此需要~u修饰符。

要获取第一次出现的索引,请使用带有preg_match标志的PREG_OFFSET_CAPTURE函数。以下是您在评论中提供的简化的正则表达式:

preg_match('~(?<!т\.н)(?<!т\.к)(?<!e\.g)\.(?=\s+\p{L})~iu', $text, $match, PREG_OFFSET_CAPTURE);

看到前瞻一个接一个地执行,并且在字符串中的相同位置,因此,您不必另外将它们分组到正向前瞻中。请参阅regex demo

IDEONE demo

$re = '~(?<!т\.н)(?<!т\.к)(?<!e\.g)\.(?=\s+\p{L})~iu';
$str = "cats, e.g. Barsik, are funny. And it is true. So,"; 
preg_match($re, $str, $match, PREG_OFFSET_CAPTURE);
echo $match[0][1];

答案 1 :(得分:0)

以下是从初始字符串的起始位置到最后.位置获取子字符串的两种方法:

  • 使用strrpossubstr函数:

    $str = 'cats, e.g. Barsik, and e.g. Lusya are funny. And it is true. So,';
    $len = strlen($str);
    $str = substr($str, 0, (strrpos($str, '.', strrpos($str, '.') - $len - 1) - $len) + 1);
    
    print_r($str);  // "cats, e.g. Barsik, and e.g. Lusya are funny."
    
  • 使用array_reversestr_splitarray_search函数:

    $str = 'cats, e.g. Barsik, and e.g. Lusya are funny. And it is true. So,';
    $parts = array_reverse(str_split($str));
    $pos = array_search('.', $parts) + 1;
    $str = implode("", array_reverse(array_slice($parts, array_search('.', array_slice($parts, $pos)) + $pos)));
    
    print_r($str);  // "cats, e.g. Barsik, and e.g. Lusya are funny."