У меня есть регулярное выражение (php5.2 и 5.3), которому нужно извлечь первые $x предложений из сообщения пользователя (которые могут включать адреса электронной почты и гиперссылки), и у меня возникли проблемы с попыткой выяснить, почему (и да, это уродливое регулярное выражение ; Оптимизирую, когда заработает):
/^(([^.!?]+|(\w+[.@?&=%:])+\w+)+[.!?]+\s){0,4}/
возвращает первые четыре предложения, но
/^(([^.!?]+|(\w+[.@?&=%:])+\w+)+[.!?]+\s){0,5}/
не возвращает совпадений. Насколько я понимаю, {0,5} должен соответствовать предыдущей группе от 0 до 5 раз, и поэтому все равно должен работать, если он может соответствовать ей только 4 раза.
Может ли кто-нибудь пролить свет на это поведение?
Обновление: $x — просто произвольное число; используя {0,$x} в регулярном выражении. Сообщение фильтруется, чтобы быть предложениями, разделенными одним пробелом. Извините за уродливое выражение... изучаю это уже пару дней, и это делает мне голову... Сделал изменения, предложенные савой. Мой главный вопрос касается поведения, и содержание, которому соответствует группа, не должно иметь большого значения.
Update2: это, по сути, то, что я делаю:
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. Второй заменяет любые дополнительные группы пробелов одним пробелом, поэтому мы надеемся, что предложения разделены ровно одним пробелом.
((\w+[....\w)
, и вы не согласны с захватами: иногда у вас есть(...)
, а иногда у вас есть(?:...)
. Используйте первый только тогда, когда вы хотите извлечь эту часть. Я думаю, что невежливо просто публиковать сложное регулярное выражение и позволять людям следовать ему. - person sawa   schedule 29.03.2011