Loading...
a.polyanska avatar a.polyanska 107 Точки

[Homework] PHP Basics - Arrays, Strings, Objects - - Problem{6} - URL Replacer

Здравейте,

Имам проблем с мачването по регулярен израз в задачата. Като начало съм написала това:

$text = $_GET["text"];

$pattern ='/[\<a\s]+[href]+[=\"|\']+[\w:/.\d\s?=%\"]*[>]/';

$index = strpos($text, $pattern);

Текстът, в който търсим URL-а е този от примера:

<p>Come and visit <a href="http://softuni.bg">the Software University</a> to master the art of programming. You can always check our <a href="www.softuni.bg/forum">forum</a> if you have any questions.</p>

Тествах регекса и би трябвало да работи, но ми връща index= false. Пробвах и с preg_match и отново не работи. В синтаксиса ли ми е грешката и защо не открива URL-a, след като в регекс-тестера работи?

 
0
PHP Web Development Basics
nikola.m.nikolov avatar nikola.m.nikolov 830 Точки
Best Answer

Regex-а не ти е правилен. Когато искаш точен резултат не използвай []. Примерно първите скоби от твоя regex [\<a\s]+ хващат , но също така хващат и  <аааааааааааа и така до безкрай. Хващат и  <аааа<ааа<аа<. Целия ти regex хваща грешен текст заради използването на тези скоби на няколко места.

Съветът ми като за начало е да използваш http://www.phpliveregex.com/. Този сайт е подходящ за php regex-и и ти показва резултата от preg_match, preg_match_all и preg_replace.

Ето този regex е по-добре, макар че е настроен за добре форматиран a таг и то само с href в него -         <a\shref=(?:\"|\'){1}[^"']+(?:\"|\'){1}>

Може и да ти е трудно да разбереш какво прави моят regex, така че ще се опитам да го обясня доколкото мога.

Как работи preg_match_all - взема стринг и спрямо зададен pattern започва да търси съвпадения. Ако preg_match_all е намерил съвпадение, то винаги връща Multidimensional array (масив, съдържащ в себе си 1 или повече масиви). Това съвпадение винаго го записва в index 0, който също е масив. Всяко следващо съвпадение го добавя към този масив с index 0.

<a\shref=  - всичко, което не е в [], го търси като точно съвпадение. В случая търси <а href=     /Макар че \s търси white spaces, а не само space/. Ако само 1 символ променил в стринга и го направиш примерно  <аn href= то за preg_match_all този стринг вече не отговаря на regex-a. 

**************************

(?:\"|\'){1} - със скобите () се прави група, която match_all връща като допълнителен масив с index > 0 . Идеята е следната - в index 0 preg_match_all записва всички стрингове, които отговарят на целия regex pattern. Ако в regex-a имаш група, която е в (), то preg_match_all създава index 1, който е от тип array и в него записва само това съвпадение от целия regex, което е оградено в тези скоби. Ако имаш втора група, оградена с (), то ще има index 2, в чиито масив ще са съвпаденията от тази група.

Ето нагледен Пример  - за regex сложи <a\shref=\"([^>]+)\"> , защото линка чупи regex-a и избери в дясно preg_match_all. Index 0 е масив, в който са записани всички намерени съвпадения спрямо целия regex. Index 1 пък е масив, в който е записана само информацията, която се намира вътре в "" на href. Този index 1 се създава, защото това, което regex-a търси в скобите съм го направил група с използването на () - ([^>]+).

Ако надградим предния пример да търси A таг, в който освен атрибут href има и target то ще имаме следния Пример с regex: <a\shref=\"([^>]+)\" target=\"([^>]+)\"> . В този regex имаме вече 2 групи с () - първата за това, което е в "" на href и втората за това, което е в "" на target. Резултатите от първата група са в index 1, а от втората в index 2.

Понякога може да ти се наложи да използваш група в regex-a, но да не искаш preg_match_all да записва резултата за нея. Това може да се направи като се използва (?:). На мен ми се налага понякога да използвам група, която не искам да записвам в резултата, когато използвам | (Or). В regex-a ми за задачата използвам (?:\"|\') {1} - по този начин търся символ " ИЛИ ', като с {1} указвам, че търся само 1 такъв символ. В този пример ако {1} се махне regex-a пак ще работи, но го добавих заради обясненията. 

2
14/12/2014 13:05:35
VenelinGrozev avatar VenelinGrozev 130 Точки

Проблемът е в регекса сякаш - в http://www.regexr.com/ оригиналният му вариант показва съвпадения. Когато го минеш през preg_match_all обаче връща грешка Warning: preg_match_all(): Unknown modifier '.'

Трябва да ескейпнеш наклонената черта надясно преди точката и ще заработи $pattern ='/[\<a\s]+[href]+[=\"|\']+[\w:\/.\d\s?=%\"]*[>]/';

1
14/12/2014 06:20:32
Можем ли да използваме бисквитки?
Ние използваме бисквитки и подобни технологии, за да предоставим нашите услуги. Можете да се съгласите с всички или част от тях.
Назад
Функционални
Използваме бисквитки и подобни технологии, за да предоставим нашите услуги. Използваме „сесийни“ бисквитки, за да Ви идентифицираме временно. Те се пазят само по време на активната употреба на услугите ни. След излизане от приложението, затваряне на браузъра или мобилното устройство, данните се трият. Използваме бисквитки, за да предоставим опцията „Запомни Ме“, която Ви позволява да използвате нашите услуги без да предоставяте потребителско име и парола. Допълнително е възможно да използваме бисквитки за да съхраняваме различни малки настройки, като избор на езика, позиции на менюта и персонализирано съдържание. Използваме бисквитки и за измерване на маркетинговите ни усилия.
Рекламни
Използваме бисквитки, за да измерваме маркетинг ефективността ни, броене на посещения, както и за проследяването дали дадено електронно писмо е било отворено.