2016-06-14 100 views
1

我有一些字符串,例如:如何從字符串的開頭到第二個最後一個字符串切斷字符串?

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(); 

但它得到第二點的位置(在詞「真」之後)。

如何獲得所需的結果?

+5

你的標題是誤導性的,因爲你需要匹配的第一個句號表示句子的結束。這是一種天真的做法:'〜(?<!\ be \ .g)\。(?= \ s + \ p {Lu})〜''(用於'preg_match')。但是,您可能需要某種NLP包。 –

+0

@WiktorStribiżew,謝謝 – mnv

+0

還有其他縮寫,這不適用於所有情況。 –

回答

1

由於天真的方法適合你,我發佈了一個答案。但是,請注意,檢測句子結束對於正則表達式來說是一項非常困難的任務,儘管可能在某種程度上可能會使用NLP包。

說了這麼多,我建議使用

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

正則表達式是不是前面有一個完整的單詞e.g任何點(\.)匹配(見負回顧後(?<!\be\.g)),但隨後用1或更多空格(\s+)後跟1個大寫Unicode字母\p{Lu}

regex demo

不區分大小寫i修改不會影響什麼\p{Lu}匹配。

由於您使用的是Unicode文本(如俄語),因此需要使用~u修飾符。

要獲得第一個匹配項的索引,請使用帶有PREG_OFFSET_CAPTURE標誌的preg_match函數。這裏是你的意見提供了一下簡化的正則表達式:

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]; 
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." 
    
相關問題