PCRE Regex Синтаксис

Предполагам, че това е повече или по-малко въпрос от две части, но ето първо основите: пиша малко PHP, за да използвам preg_match_all, за да търся в променлива низове, завършващи книга от {}. След това преминава през всеки върнат низ, заменя намерените низове с данни от MySQL заявка.

Първият въпрос е следният: Има ли добри сайтове, където наистина да научите тънкостите на PCRE изразите? Търсих много в Google, но най-доброто, което успях да намеря досега, е http://www.regular-expressions.info/. По мое мнение информацията там не е добре организирана и тъй като предпочитам да не се налага да моля за помощ, когато трябва да напиша сложен регулярен израз, моля, насочете ме към няколко сайта (или няколко книги!) това ще ми помогне да не ви безпокоя в бъдеще.

Вторият въпрос е следният: имам този регулярен израз

"/{.*(_){1}(.*(_){1}[a-z]{1}|.*)}/"

и имам нужда от него, за да хвана случаи като {first_name}, {last_name}, {email} и т.н. Имам три проблема с този регулярен израз.

Първото е, че вижда "{first_name} {last_name}" като един низ, когато трябва да го вижда като два. Успях да разреша това, като проверих съществуването на пространството, след което експлодирах върху пространството. Объркано, но работи.

Вторият проблем е, че включва препинателни знаци като част от заснетия низ. Така че, ако имате "{first_name} {last_name},", то връща запетаята като част от низа. Успях частично да разреша това, като просто използвах preg_replace за изтриване на точки, запетаи и точки и запетая. Въпреки че работи за тези препинателни знаци, моята логика не може да се справи с удивителни знаци, въпросителни знаци и всичко останало.

Третият проблем, който имам с този регулярен израз, е, че той изобщо не вижда екземпляри на {email}.

Сега, ако можете, желаете и имате време просто да ми дадете решението на този проблем, благодаря ви, тъй като това ще реши непосредствения ми проблем. Въпреки това, дори ако можете да направите това, моля, моля предоставете lmgfty, който предоставя добри уеб сайтове като препратки и/или книга или две, които биха предоставили добро образование по този въпрос. Сайтовете биха били за предпочитане, тъй като парите са ограничени, но ако решението е книга, ще намеря парите (ако приемем, че моята местна библиотечна система не е в състояние да осигури въпросния том).


person Clement Smith    schedule 04.06.2012    source източник
comment
Много ми хареса книгата Овладяване на регулярни изрази. В тази книга има повече, отколкото вероятно някога ще използвате; много задълбочено.   -  person Jonah Bishop    schedule 05.06.2012
comment
@JonahBishop: това е хубава книга, но не съвсем лесна за смилане ;)   -  person 0xC0000022L    schedule 05.06.2012
comment
@ClementSmith: казвате, че трябва да го вижда като две, но регулярният ви израз е алчен. Добавете няколко ? на правилните места :)   -  person 0xC0000022L    schedule 05.06.2012
comment
@JonahBishop: Благодаря ви за това предложение. Имам тази книга по поръчка от библиотеката. Трябва да е тук следващата седмица.   -  person Clement Smith    schedule 05.06.2012


Отговори (3)


Тогава намерих справката за PCRE синтаксис на PHP за доста добра: http://uk.php.net/manual/en/reference.pcre.pattern.syntax.php

Нека поговорим за изражението ви. Това е доста по-подробно от необходимото; Ще го опростя, докато минаваме през това.

Доста по-опростен начин за разглеждане на това, което се опитвате да съпоставите: „намерете {, след това произволен брой букви или долни черти, след това }“. Редовен израз за това е (в синтаксиса string-y на PHP): '/\{[a-z_]+\}/'

Това ще съвпадне с всички ваши примери, но и с някои по-диви като {__a_b}. Ако това не е опция, можем да отидем с малко по-сложно описание: „намерете {, след това куп букви, след това (колкото е възможно по-често) долна черта, последвана от куп букви, след това }“. В регулярен израз: /\{([a-z]+(_[a-z]+)*\}/

Това второто може би се нуждае от малко повече обяснение. Тъй като искаме да повторим нещото, което съвпада с _foo сегмента, трябва да го поставим в скоби. Тогава казваме: опитайте се да намерите това възможно най-често, но също така е добре, ако изобщо не го намерите (това е значението на *).

Така че сега, когато имаме с какво да сравним опита ви, нека да разгледаме какво е причинило проблемите ви:

  • Вашият израз съвпада с всички знаци в {}, включително } и { и цял куп други неща. С други думи, {abcde{_fgh} ще бъде приет от вашия регулярен израз, както и {abcde} fg_h {ijkl}.
  • Имате задължително _ там, веднага след първото .*. (_){1} (което означава абсолютно същото като _) казва: каквото и да се случи, експлодирайте, ако това не е тук! Очевидно всъщност не искате това, защото никога няма да съвпадне с {email}.

Ето пълно описание на обикновен език на това, на което съответства вашият регулярен израз:

  1. Съпоставете {.
  2. Съпоставете _.
  3. Сравнете абсолютно всичко, стига да можете да сравните всички останали правила веднага след това каквото и да било.
  4. Съпоставете _.
  5. Свържи една буква.
  6. Вместо това _ и единствената буква, абсолютно всичко също е наред.
  7. Съпоставете }.

Това вероятно е доста далеч от това, което искахте. Не се тревожете обаче. Регулярните изрази отнемат известно време, за да свикнете. Мисля, че е много полезно, ако мислите за това от гледна точка на инструкции, т.е. когато създавате регулярен израз, опитайте се да го изградите в главата си като „намерете това, след това намерете онова“ и т.н. След това измислете правилния синтаксис, за да постигнете точно това.

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

Късмет! :)

person Jan Krüger    schedule 04.06.2012
comment
Благодаря ви за това. Не се бях замислял да мисля за регулярните изрази по този начин преди. Предполагам, че се дължи на неопитност, наистина. Оценявам отговора ви и маркирах тази страница като книга за бъдещи справки. (Получих и книгата, предложена от @JonahBishop, по поръчка от библиотеката) - person Clement Smith; 05.06.2012

За PCRE просто усвоих страниците с ръководство на PCRE, но мозъкът ми така или иначе работи по този начин...

Що се отнася до съпоставянето на разграничени неща, обикновено имате 2 подхода:

  1. Съпоставете първия разделител, съпоставете всичко, което не е затварящият разделител, съпоставете затварящия разделител.
  2. Съпоставете първия разделител, съпоставете всичко нелакомо, съпоставете затварящия разделител.

напр. за твоя случай:

  1. \{([^}]+)\}
  2. \{(.+?)\} - Обърнете внимание на ? след +

Добавих група около съдържанието, което вероятно също искате да извлечете.

Обърнете внимание също така, че в случай на #1 по-специално, но също и за #2, ако „точката съвпада с нещо“ е в сила (dotall, singleline или както го нарича любимата ви разновидност на регулярния израз), че те също ще съответстват на прекъсвания на редове в рамките - вие бихте трябва ръчно да изключите това и всичко друго, което не искате, ако това би представлявало проблем; вижте горния отговор, ако искате нещо повече като подход с бял списък.

person ChrisF    schedule 05.02.2013

Добавих връзка, показваща, че регулярният израз работи. Може би го проверете и ми кажете какъв според вас е проблемът, който имате. Внимавайте да не поставяте интервали в края на регулярния израз, когато го използвате - забелязах, когато го копирах, за да го тествам, че взех някои завършващи интервали, които го спряха да работи правилно.
person Carl    schedule 21.11.2014