отрицательный взгляд назад и жадные квантификаторы в php - PullRequest
5 голосов
/ 15 октября 2010

Я использую регулярное выражение, чтобы найти любые URL и связать их соответственно.Однако я не хочу связывать какие-либо URL-адреса, которые уже связаны, поэтому я использую lookbehind, чтобы увидеть, есть ли перед URL-адресом href.Это терпит неудачу, потому что квантификаторы переменной длины не разрешены в lookahead и lookbehind для PHP.

Вот регулярное выражение для совпадения:

/\b(?<!href\s*=\s*[\'\"])((?:http:\/\/|www\.)\S*?)(?=\s|$)/i

Как лучше всего решить эту проблему?

РЕДАКТИРОВАТЬ:

Мне еще предстоит проверить это, но я думаю, что хитрость в том, чтобы сделать это в одном регулярном выражении, заключается в использовании условных выражений в регулярном выражении, которое поддерживается PCRE.Это выглядело бы примерно так:

/(href\s*=\s*[\'\"])?(?(1)^|)((?:http:\/\/|www\.)\w[\w\d\.\/]*)(?=\s|$)/i

Ключевым моментом является то, что, если href захвачен, совпадение сразу же выбрасывается из-за условного (?(1)^|), которое гарантированно не будет совпадать.Вероятно, что-то не так с этим.Я проверю это завтра.

Ответы [ 3 ]

1 голос
/ 15 октября 2010

Я попытался сделать то же самое, наоборот: убедитесь, что URL не заканчивается ">:

/((?:http:\/\/|www\.)(?:[^"\s]|"[^>]|(*FAIL))*?)(?=\s|$)/i

Но для меня это выглядит довольно странно, я уверен, что вы можетесделай лучше.

Мой второй подход больше похож на твой (и, следовательно, более точен):

/href\s*=\s*"[^"]*"(*SKIP)(*FAIL)|((?:http:\/\/|www\.)\S*?)(?=\s|$)/i

Если я найду href= I (*SKIP)(*FAIL).Это означает, что я прыгаю в положение, в котором находится движок регулярных выражений, когда он встречает (*SKIP).

Но это не менее хакерски, и я уверен, что есть лучшая альтернатива.

0 голосов
/ 15 октября 2010

Поиск «каждого URL, который не является частью ссылки» - довольно сложная негативная логика.Может быть проще найти каждый URL, затем каждый URL, являющийся ссылкой, и удалить каждый из последних из предыдущего списка.

Что касается определения того, какие URL являются частьюссылка, попробуйте:

/<a([\s]+[\w="]+)*[\s]+href[\s]*=[\s]*"([\w\s:/.?+&=]+)"([\s]+[\w="]+)*>/i

Я проверил это с http://regexpal.com/, чтобы быть уверенным.Сначала он ищет <a, затем учитывает любое количество параметров, затем следует href и любое другое количество параметров.Если у него нет href, это не ссылка.Если это не тег <a>, это не ссылка.Поскольку это просто список того, что мы хотим удалить из другого списка (URL-адресов), я упростил определение URL-адреса до [\w\s:/.?+&=]+.Что касается создания списка URL-адресов, вам понадобится что-то более умное.

0 голосов
/ 15 октября 2010

У меня нет лучшего регулярного выражения.но если вы не найдете лучшего выражения, я бы предложил использовать два запроса для этой задачи.Сначала найдите и удалите все ссылки, а затем найдите URL-адреса.Это было бы проще и быстрее, возможно.(Для поиска и замены вы можете использовать что-то вроде - http://www.satya -weblog.com / 2010/08 / php-regex-find-and-replace-any-word-string-or-text-при-один-go.html ).

...