Отрицание в регулярном выражении

BoRay

Новичок
Отрицание в регулярном выражении

Добрый день!

Не могу разобраться с отрицанием в регулярном выражении(

Нужно заменить в тексте все ссылки на свои кроме тех что имеют href="www.url.ru"

PHP:
$page =   // - боооольшой текст со ссылками

$find = "/<a.+ href.*=.*[\"|'].*[^www\.url\.ru].*[\"|'].*a>/";
$whot = "my_text";

preg_replace($find, $my_text,  $page);
Что не так делаю?

Спасибо за внимание!
 

BoRay

Новичок
Автор оригинала: Вурдалак
Через callback-функцию пропускай адрес
Помоему чушь какая-то сказана... А если я не прав - поподробнее.

ПС. У меня проблема с регулярным выражением, а не с заменой. Если писать без отрицания, то она будет менять www.url.ru на мой_урл. А мне нужно чтобы все другие урлы менялись.
 

freeek

Новичок
Re: Отрицание в регулярном выражении

Автор оригинала: BoRay
Добрый день!

Не могу разобраться с отрицанием в регулярном выражении(

Нужно заменить в тексте все ссылки на свои кроме тех что имеют href="www.url.ru"

PHP:
$page =   // - боооольшой текст со ссылками

$find = "/<a.+ href.*=.*[\"|'].*[^www\.url\.ru].*[\"|'].*a>/";
$whot = "my_text";

preg_replace($find, $my_text,  $page);
Что не так делаю?

Спасибо за внимание!
PHP:
$regex = '%(<a.*href=\Whttp\:\/\/)(?!www\.url\.ru)((?:.*\.)?[a-z0-9-]+\.[a-z]{2,5})(.*\W[^>]*>)%iUs';
echo preg_replace( $regex, '$1mylink.com$3', $readfile )
 

BoRay

Новичок
Re: Re: Отрицание в регулярном выражении

Автор оригинала: freeek
PHP:
$regex = '%(<a.*href=\Whttp\:\/\/)(?!www\.url\.ru)((?:.*\.)?[a-z0-9-]+\.[a-z]{2,5})(.*\W[^>]*>)%iUs';
echo preg_replace( $regex, '$1mylink.com$3', $readfile )
Ух, серьезно) Ну сейчас буду разбираться чего тут написано) Спасип...
 

varan

Б̈́̈̽ͮͣ̈Л̩̲̮̻̤̹͓ДͦЖ̯̙̭̥̑͆А͇̠̱͓͇̾ͨД͙͈̰̳͈͛ͅ
Re: Re: Отрицание в регулярном выражении

Автор оригинала: freeek
PHP:
$regex = '%(<a.*href=\Whttp\:\/\/)(?!www\.url\.ru)((?:.*\.)?[a-z0-9-]+\.[a-z]{2,5})(.*\W[^>]*>)%iUs';
echo preg_replace( $regex, '$1mylink.com$3', $readfile )
Да ну нафиг такие шарады, лучше уж через callback
 

freeek

Новичок
Re: Re: Re: Отрицание в регулярном выражении

вот так наверное правильней будет

PHP:
$regex = '%(<a.*href=(?:\'|\")http\:\/\/)(?!www\.url\.ru)([a-z0-9-\.]+?.*)((?:\'|\")[^>]*>)%iUs';
 

BoRay

Новичок
Re: Re: Re: Re: Отрицание в регулярном выражении

Автор оригинала: freeek
вот так наверное правильней будет

PHP:
$regex = '%(<a.*href=(?:\'|\")http\:\/\/)(?!www\.url\.ru)([a-z0-9-\.]+?.*)((?:\'|\")[^>]*>)%iUs';
Ога, почти разобрался. Не понятен вот какой момент - $regex = '%(<a.*href=(?:\'|\")http\:\/\/)(?!www\.url\.ru)([a-z0-9-\.]+? .*)((?:\'|\")[^>]*>)%iUs';
Выделенное красным - зачем оно тут?
И что значит конструкция [^>]* ?
 

grigori

( ͡° ͜ʖ ͡°)
Команда форума
а зачем тебе парсить ссылки на страницы?
это может нарушать правила форума
 

freeek

Новичок
у нас стои модификатор U который инвертирует жадность
т.е. рега не хаватет все от и до
а когда ?то мы инвертируем обратно
т.е. захватываем наибольшее кол-во символов подпадающее подправило

смысл в том что изначльно реги жадные и если б мы использовали регу по захвату данного тега, то рега захватила б от начала открытия до конца последнего тега

-~{}~ 06.10.09 00:00:

уриво объяснил, конечно

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

BoRay

Новичок
Автор оригинала: dimagolov
[] это символьный класс, ^ это отрицание в нем, то есть [^>] это "все кроме >", ну а * это любое кол-во повторов, начиная с 0.
Ок, как изначально я и предполагал. а почему тогда не работал мой регулярник?
PHP:
/<a.+ href.*=.*[\"|'].*[^www\.url\.ru]+.*[\"|'].*a>/
логика то вроде такая....

-~{}~ 06.10.09 11:38:

Автор оригинала: grigori
а зачем тебе парсить ссылки на страницы?
это может нарушать правила форума
Мне нужно блокировать ссылки(<noindex>) в автомате.

-~{}~ 06.10.09 11:41:

Автор оригинала: freeek
у нас стои модификатор U который инвертирует жадность
т.е. рега не хаватет все от и до
а когда ?то мы инвертируем обратно
т.е. захватываем наибольшее кол-во символов подпадающее подправило

смысл в том что изначльно реги жадные и если б мы использовали регу по захвату данного тега, то рега захватила б от начала открытия до конца последнего тега

-~{}~ 06.10.09 00:00:

уриво объяснил, конечно

т.е. изначльно мы сделали регу нежадной, а в нужном месте сделали ее жадной
Спасибо, мне нужно мануалы покурить теперь.
 

freeek

Новичок
Автор оригинала: BoRay
Ок, как изначально я и предполагал. а почему тогда не работал мой регулярник?
PHP:
/<a.+ href.*=.*[\"|'].*[^www\.url\.ru]+.*[\"|'].*a>/
логика то вроде такая....
ну это только кажется что такая

1) для начала надо определиться что мы будем искать
ты хочешь
PHP:
'<a>.*</a>'
я предлагаю работать только с
PHP:
'<a>'
2) так как ссылок в тексте может быть много, надо сделать регу нежадной U, так есть переносы s и i для регистронезависимого поиска
3) по сути начало тега можно представить в виде
PHP:
'%<a[^>]*>%iUs'
, т.е. открывающий тег, все что угодно кроме закрывающего и сам закрывающий
4) потом эту конструкцию расширяем, так как нам интересен href его и ищем в первую очередь, что то типа:
PHP:
'%<a.*href[^>]*>%iUs'
5) на нужно значение href, поэтому в этом шаге мы ищем его:
PHP:
'<a.*href=(?:\'|\")(.*)(?:\'|\")[^>]*>%iUs'
. мы использовали
PHP:
(?:a|b)
вместо символьного класса
PHP:
[]
, так как это уместней,
PHP:
?:
чтобы не захватывало подмаску
6) смотрим на сам урл, ну тут уже все персонально, главная мысль используем http\:\/\/ для индетефикации (в общем виде, может и не быть если ссылка относительная и т.д.):
PHP:
 '%<a.*href=(?:\'|\")http\:\/\/(.*)(?:\'|\")[^>]*>%iUs'
7) а теперь выбираем тот который нам подходит, в данном случае, если нам надо выбрать все урлы, доменные имена которых не равны www.url.com, пишем
PHP:
 '%<a.*href=(?:\'|\")http\:\/\/(?!www\.url\.com)(.*)(?:'|\")[^>]*>%iUs'
,
PHP:
 (?!www\.url\.com)
- отрицательное утверждение после позиции
PHP:
 http\:\/\/
, смысл его в том что,- мы вибераем все значения гссылок в которых доменными именами не может быть
PHP:
 www\.url\.com
, ну или просто все анкоры в которых после
PHP:
 href=(?:\'|\")http\:\/\/
не следует
PHP:
 (?!www\.url\.com)
, а дальше описывем ссылку как
PHP:
 .*
ну или как я предложил ранее в виде символьного класса
PHP:
 [a-z0-9-\.]+?.*
, это для того чтобы отделить доменные имя


1) ты хочешь схватить сразу весь тег с содержимым
2) вместо отрицательного утверждения после http:// или '," неважно, ты использовал символьный класс, которй можно описать как любые символы кроме те [^www\.url\.ru], это можно записать проще как [^wurl\.] - понятно, что это и не пахнет www\.url\.ru

эти два момента, первый в меньшей степени (потому как это можно представить и ввиде
PHP:
'%<a.*href=(?:\'|\")http\:\/\/(?!www\.url\.ru).*(?:\'|\").*(?=a>)a>%iUs'
), а в основном второй, который и есть ошибкойв данном случае
 

BoRay

Новичок
Автор оригинала: freeek
ну это только кажется что такая

1) для начала надо определиться что мы будем искать
ты хочешь
PHP:
'<a>.*</a>'
я предлагаю работать только с
PHP:
'<a>'
2) так как ссылок в тексте может быть много, надо сделать регу нежадной U, так есть переносы s и i для регистронезависимого поиска
3) по сути начало тега можно представить в виде
PHP:
'%<a[^>]*>%iUs'
, т.е. открывающий тег, все что угодно кроме закрывающего и сам закрывающий
4) потом эту конструкцию расширяем, так как нам интересен href его и ищем в первую очередь, что то типа:
PHP:
'%<a.*href[^>]*>%iUs'
5) на нужно значение href, поэтому в этом шаге мы ищем его:
PHP:
'<a.*href=(?:\'|\")(.*)(?:\'|\")[^>]*>%iUs'
. мы использовали
PHP:
(?:a|b)
вместо символьного класса
PHP:
[]
, так как это уместней,
PHP:
?:
чтобы не захватывало подмаску
6) смотрим на сам урл, ну тут уже все персонально, главная мысль используем http\:\/\/ для индетефикации (в общем виде, может и не быть если ссылка относительная и т.д.):
PHP:
 '%<a.*href=(?:\'|\")http\:\/\/(.*)(?:\'|\")[^>]*>%iUs'
7) а теперь выбираем тот который нам подходит, в данном случае, если нам надо выбрать все урлы, доменные имена которых не равны www.url.com, пишем
PHP:
 '%<a.*href=(?:\'|\")http\:\/\/(?!www\.url\.com)(.*)(?:'|\")[^>]*>%iUs'
,
PHP:
 (?!www\.url\.com)
- отрицательное утверждение после позиции
PHP:
 http\:\/\/
, смысл его в том что,- мы вибераем все значения гссылок в которых доменными именами не может быть
PHP:
 www\.url\.com
, ну или просто все анкоры в которых после
PHP:
 href=(?:\'|\")http\:\/\/
не следует
PHP:
 (?!www\.url\.com)
, а дальше описывем ссылку как
PHP:
 .*
ну или как я предложил ранее в виде символьного класса
PHP:
 [a-z0-9-\.]+?.*
, это для того чтобы отделить доменные имя


1) ты хочешь схватить сразу весь тег с содержимым
2) вместо отрицательного утверждения после http:// или '," неважно, ты использовал символьный класс, которй можно описать как любые символы кроме те [^www\.url\.ru], это можно записать проще как [^wurl\.] - понятно, что это и не пахнет www\.url\.ru

эти два момента, первый в меньшей степени (потому как это можно представить и ввиде
PHP:
'%<a.*href=(?:\'|\")http\:\/\/(?!www\.url\.ru).*(?:\'|\").*(?=a>)a>%iUs'
), а в основном второй, который и есть ошибкойв данном случае
Респект! Очень все понятно объяснил.
 
Сверху