У меня есть (php5.2 и 5.3) регулярное выражение, которому необходимо извлечь первые $ x предложений из поста пользователя (который может включать адреса электронной почты и гиперссылки), и мне не удается выяснить, почему (и да, это отвратительное регулярное выражение; я оптимизирую его, когда оно будет работать):
/^(([^.!?]+|(\w+[.@?&=%:])+\w+)+[.!?]+\s){0,4}/
возвращает первые четыре предложения, но
/^(([^.!?]+|(\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];
}
Предложение (по крайней мере, на мой взгляд, без перехода на территорию НЛП, потому что оно предназначено только для одной функции на сайте) - это что-то до точки, восклицательного знака или вопросительного знака, но точки могут появляться в предложении в виде адрес электронной почты URL. Последняя версия этого регулярного выражения просто насчитывала до 5 периодов и, таким образом, разбивалась по ссылкам и адресам электронной почты.
Обновление 3: Учитывая, что я только что добавил еще более ужасный код, я объясню последнее. Было обнаружено, что в некоторых опубликованных материалах есть непечатаемые символы (например, \ r и т. Д.), Которые не очень хорошо работают с регулярным выражением, поэтому я удаляю непечатные символы с первым preg_replace. Второй заменяет любые дальнейшие группы пробелов одним пробелом, поэтому, мы надеемся, предложения разделены ровно одним пробелом.