Универсальный код деления на предложения...

Статус
В этой теме нельзя размещать новые ответы.
Во втором коде ошибка, поправил.
 
Тестировал ваш код на большом кол-ве предложений.
Работает стабильно, особенно если выкинуть вот этот участок, отвечающий за сокращения.
Код:
if (preg_match('/(?<=[^.]\.)\G(?!\.)/', $text, $w, 0, $i) && in_array($m[1][0], $sokr))  {
       $s=true;
   } else {
       $s=false;
   }
Если не выкинуть этот участок, то php случайным образом вылетает, закономерность на тексте не удалось определить.
Теперь планирую получившие предложения еще раз прогнать скриптом, чтобы их склеить, если на концах предложения встречаются сокращения и по возможности обработать конструкции вида: Фамилия И.О. и И. О. Фамилия.
Такие вещи разбиваются как разные предложения.
Спасибо за ваш скрипт, даже с учетом мелких замечаний, класнный.
Кстати если кто будет разбивать текст в юникоде, не забудте в регулярках дописать модификатор "u".

Не могли бы вы разъяснить смысл вот этого регулярного выражения
Код:
preg_match('/(?<=[^.]\.)\G(?!\.)/', $text, $w, 0, $i)
он вроде бы отвечает за выделение на конце предложения сокращения, как думаете его можно заменить вот таким выражением:
Код:
preg_match('/\s([а-яё]+)\.$/ui', $txt, $m, PREG_OFFSET_CAPTURE)
 
Выкидывать этот участок не разумно, тогда уже весь код с while и использовать регулярку в preg_match_all. Или использовать первую регулрку, на маленькой базе сокращений она будет шустрее.
Если не выкинуть этот участок, то php случайным образом вылетает, закономерность на тексте не удалось определить.
Дайте текст на котором вылетает.
Не могли бы вы разъяснить смысл вот этого регулярного выражения
Это выражение проверяет, на чем произошел разрыв предложения. Если это одна точка, то выполняется дополнительная проверка, не является ли последнее слово сокращением.
Его стоит переделать вот так, возможно тогда и вылетать перестанет.
Код:
preg_match('/\G(?<=[а-яёa-z]\.)/i', $text, $w, 0, $i)
Хотя еще лучше включить эту проверку в первую регулярку, вот так
PHP:
$re='
{
\G(?:
    ([а-яa-z]++)|
    [^.\n?!а-яa-z\d("]++(?:[!\?]++)?|
    \.(?:\.*+)
       [^а-яa-z.?!\n]*+(?:\n[^а-яa-z.?!\n]*+)?
       (?=(?-i:[а-яa-z]))|
    (?<=\b[а-юa-z])\.|
    \n[^а-яa-z.?!\n]*+(?=(?-i:[а-яa-z]))|
    \d++(?:\.\d++)?|
    (?:"(?=[^\s.]).*?(?<=[^\s])"|")|
    (?:\((?=[^\s.]).*?(?<=[^\s])\)|\( )
)+
[?!\n.]*
((?<=[а-яёa-z]\.))?
}isx';

$i=0;
$s=false;
while (preg_match($re, $text, $m, PREG_OFFSET_CAPTURE, $i)) {
   if($s) {
      $predl[count($predl)-1].=$m[0][0];
   } else {
      $predl[]=$m[0][0];
   }
   $i=$m[0][1]+strlen($m[0][0]);
   if (isset($m[2]) && in_array($m[1][0], $sokr))  {
       $s=true;
   } else {
       $s=false;
   }
}
Вообще, здесь есть куда улучшать, этот код я писал для примера. Например вместо массива наверно лучше исползовать хеш(ассоциативный масив). Можно включить в регулярку кавычки типа «» „“

Добавлено через 9 минут
Найти фамилии можно так
Код:
{\b(?:[А-Я]\.\ *[А-Я]\.\ +[A-Я][а-я]+|
[A-Я][а-я]+\ +[А-Я]\.\ *[А-Я]\.)}x
А зачем разбивать по фамилиям?
 
как правильно написать $sokr ???

для Ф.И.О., т.д., т.п., и.о.,
если предложение заканчивается так - т. д.)!
 
Статус
В этой теме нельзя размещать новые ответы.
Назад
Сверху