|
Регулярните изрази ни позволяват да търсим шаблони в нашите данни. Използвайки правилата на регулярните изрази можем да използваме една единствена стойност (шаблон), за да опишем търсеното от нас в по-общи граници. Регулярните изрази са много голяма тема и тази глава ще ви запознае само с принципите на тяхното писане. Ако искате да вникнете в тънкостите на регулярните изрази пишете програми и експериментирайте.
Може да употребите регулярните изрази за три различни неща :съвпадение, заместване и транслитерация. Операцията по съвпадение използва оператора m/шаблон/, който връща истина или лъжа, в зависимост от това дали шаблона е намерен или не. Операцията заместване, замества един израз с друг и използва оператора s/шаблон/заместващ шаблон/. Транслитерацията замества един или повече символа с други и използва оператора tr/символ/заместващи символи/. Всички те работят с променливата по подразбиране $_. По късно ще разберете как те може да се използват и върху други променливи. Ако мястото на шаблона е празно Perl използва последния дефиниран шаблон. Това е причината, понякога да виждате на пръв поглед една конструкция със странно условие - if // {...}. Всеки регулярен израз позволява да се използват алтернативни разделители на шаблона вместо //. Това може да са {},||,[],!! и т.н. Ето пример и за ползата от това: CODE
Разбира се нищо не ви пречи да поставите шаблона в променлива, която след това да поставите в оператора за съвпадение : CODE
Ако изберете за алтернативен разделител апострофи, то ще загубите интерполацията на променливите в шаблона. Ето и просто използване на регулярен израз: CODE
Тъй като оператора m// е най-често използвания, то perl позволява той да се изпуска. CODE
Оператора за съвпадение притежава няколко допълнителни опции, които разширяват неговата функционалност: CODE
Тези опции се поставят след крайния раделител на шаблона. Ето пример за използването на опцията i : CODE
Оператора за заместване се използва за промяна на низовете. Той изисква две операнда - s/a/z/. Това ще замести първата срещната буква a с буквата z. И тук може да използвате променливи в ролята на шаблон или заместващ шаблон. CODE
И при този оператор може да използвате алтернативни разделители. Подобно на оператора за съвпадение и s///, позволява използването на опции. Те са същите като и преди, но с една допълнително. Това е опцията "/е". Тя казва на perl да изчисли шаблона за заместване като израз. Това ще ви позволи да намери всички числа в низа и да ги умножите с някакъв процент, например. Ако използвате тази опция, интерполацията на променливи се включва даже и да използвате апострофи. Разгледайте следния ред: CODE
Това, което прави този ред е да замести sometext с изхода на досовската команда dir. Оператора за транслитерация, който свързва знаковете в двата си аргумента един по един и да използва тези двойки за заместване на отделни знакове в дадения низ. Например tr/abc/xyz/ ще замести а с x, b с y и c с z. Ето пример за използването му: CODE
Ако в дясната част е празна (tr/abc//), то транслитерация няма да се осъществи и низа няма да се промени. Това може да се промени ако се използва опцията /d. Чрез нея казваме на perl да изтрие знака от лявата част, който няма свързващ знак отдясно. До тук работихме само с променливата $_. Ами ако искаме да работим с други променливи? Perl разбира се не ни ограничава и затова добавя два нови оператора =~ и !~. Те позволяват да свържем регулерните изрази към променлива различна от $_. Оператора =~ връща 1 ако шаблона е намерен в низа и недефинирана стойност ако не е. Обратно !~ връща 1 ако шаблона не е намерен и недефинирана стойност ако е намерен в низа.Ето малък пример демонстриращ действието им: CODE
Дотук разгледаните шаблони, не показват пълната мощ на регулярните изрази. Затова сега ще засегнем темата, как се създават шаблоните. Това става благодарение на т.нар. метазнакове. Това са знаци, които имат значение различно от литералното и това е подразбиращото им значение в регулярните изрази. Ако искате даден метазнак да има своето литерално значение в регулярен израз, то пред него трябва да сложите префикса "". Регулярните изрази донякъде работят като кавички. Така, че вътре в тях се извършва интерполация. Важно е да знаете, че интерполацията е само на едно ниво т.е. ако имате променлива $scalar и тя съдържа низ, с друга променлива, интерполация се извършва само на променливата $scalar. Всеки символ в регулярния израз съвпада само със себе си. Изключение правят символите $, @ , & и метазнаковете. Ако искате да използвате някои от тях в буквалното си значение е необходимо да сложите пред него обратно наклонена черта. Ето и таблица с метазнаковете: CODE
Тази голяма таблица не трябва да ви притеснява. Повечето от показаните метасимволи се използват много рядко. Знакови класове: Квадратните скоби се използват за създаването на знакови класове. Той служи за съвпадение с определен тип знак. Например, за да създадете шаблон, който да съвпадне с всяко число може да използвате следното: m/[0123456789]/. Това ще съвпадне с единичен знак от 0 до 9. Символни знакови класове: Има няколко знакови класове, толкова често използване, че Perl позволява техния кратък запис. Това са d, D, w, W, s и S. Те са обяснени в таблицата. Котви: Знака ^ се нарича котва и има за цел да накара шаблона да съвпадне с началото на низа. Знака $ има същото действие, но за края на низа. ^ се поставя винаги в началото на низа, а $ - в края. Например m/^one/ ще съвпадне само ако низа започва с комбинацията от знакове one. Обратно, шаблона m/(last|next)$/ ще съвпадне с низа, само ако той завършва с last или next. Метазнаковете A и Z също може да се използват в ролята на котви. Повторения: Повторенията са няколко метазнака, които контролират колко пъти да съвпадне дадения символ или група от символи. Например m/a{5} ще съвпадне само ако низа съдържа 5 символа "а" последователно. Такива символи още са *, +, и ?. Обратни референции: Perl има поредица от специални променливи, в които запазва всичко, което съвпада с група кръгли скоби. Всеки път, когато види двойка кръгли скоби, Perl копира съвпадналия текст в номерирана променлива - първата съвпаднала група в $1, втората в $2 и т.н. Например след използването на шаблона m/(fish|fоwl), то променливата $1 ще има стойност fish или flow в зависимост от това, което е било намерено. Граници на думи: Метазнака b ще съвпадне с мястото между интервал и първата буква от думата. Имайте впредвид обаче, че шаблона m/bfoo/ ще съвпадне с foo, даже и да няма празни символи около думата. Той също ще съвпадне и с $foo, тъй като знака $ не е буквен символ. Шаблона m/foob/ ще съвпадне с foo , но не и foobar. Шаблона m/bwiz/ ще съвпадне с wizard, но не и с geewiz. Обратно, метазнака В ще съвпадне със всичко друго освен граница на дума. Метазнак за кавички: Можете да използвате метазнаковете в тяхното буквално значение, ако използвате Q. Този метазнак запазва своето действие до края на шаблона или до намирането на метазнака E. Разширен синтаксис: (?...) позволява да използвате разширен сиснтаксис във вашите шаблони. Например (?#Some text) е т.нар. inline коментари. Комбинации: Можете да използвате всички метазнакове в каквито си поискате комбинаци, така че да създадете наистина сложни шаблони. За да се научите да използвате шаблони трябва внимателно да прочетете следващите няколко абзаца. Те ще ви обяснят как действа кода, чрез който perl извтршва търсенето на съпадения - т.нар. "машина за съвпадения". * Първо правило: След като машината започне да намира съвпадение, тя продължава да намира съвпадение по един знак наведнъж, докато е възможно. След като намери нещо, което не съвпада обаче тя трябва да спре. * Второ правило: Машината е нетърпелива. Нетърпелива е да започне и нетърпелива да спре - тя завършва проверката колкото е възможно по-напред в низа. Ако първия знак не съвпада, машината опитва да намери съвпадение при втория знак. След това използва всяка възможност да спре. * Трето правило:Машината е лакома. Ако използвате операциите + или *, те ще се опитат да откраднат колкото може повече от низа. Ако останалата част не съвпада, то машината неохотно се отказва от по един знак наведнъж и отново се опитва да намери съвпадение, за да намери възможно най-пълното съвпадение. * Четвърто правило: Машината за съвпадения мрази решенията. Ако има два клона, тя винаги ще избере първия, въпреки че втория може да й позволи да намери по-дълго съвпадение. * Обобщение: Машината регулярни изрази започва веднага щом може, взима колкото може повече, след това се опитва да завърши колкото се може по-рано, взимайки първото налично решение. Преди да започнем с примерите ще ви покажа един типичен регулярен израз : ^([0-2]d:[0-5]d:[0-5]d)s+[([^]]+)]s+(.*)$. Надявам се в края на главата да разберете какво точно прави този регулярен израз. Нека за начало да предположим, че искате да намерите първата дума от низ, който се съдържа в променливата $_. Можете да направите шаблон за съвпадение на един буквен символ: CODE
Ако искате да получите съвпадение с дума с един или два символа: CODE
По този начин може да добавите колкото си искате символа, но Perl ни предоставя по-добър начин: CODE
Това ще съвпадне с дума с един или повече буквени символа. Ако стойноста на $_ е "ААА ВВВ", то горния шаблон ще съвпадне с "ААА". Това ще ви позволи да разберете дали в низа има дума, но не и каква е тя. Тук идват на помощ обратните референции. CODE
По този начин казвате на Perl да пази стойноста на намереното в променливата $1. Когато пишете шаблони, много често ще използвате знаковите класове. Например [0123456789] ще дефинира знаков клас за десетичните цифри, а [0-9a-f] ще дефинира знаков клас за шестнайсетичните цифри. Трябва да имате впредви, че знаков клас от вида [a-9] не е валиден и perl ще прекъсне програмата с грешка. И тук може да използвате интерполация за създаване на знакови класове. Ето пример: CODE
Представете си, че ви се наложи да търсите даден символ, но не знаете колко пъти. Perl ни предоставя няколко различни метазнакове за повторения. Това са *, +, {n}, {n,} и {n,m}. Ако търсите дума, но не знаете от колко символа се състои, можете да напишете следното: CODE
Това ще съвпадне с "ААА", "ВВВВВ", но не и с " ВВВ" или " ". В случай, че имате в началото празен(и) символ(и) трябва да използвате метазнака за празен символ s последван от метазнака *. CODE
Ако решите да търсите символа, определен брой пъти може да напишете следното: CODE
Това ще съвпадне само ако низа съдържа пет думи. Това е така, защото търсим неопределен брой букви, последвани от неопределен брой празни символи, всичко това повторено пет пъти. Както казах по-горе, машината за регулярни изрази е лакома. Метазнаковете * и + ще съвпаднат с възможно най-голям брой символи: CODE
Ако искате да избегнете лакомото поведение може да използвате ?: CODE
Може би се чудите какво е $&. Ами това е една от служебните променливи на perl. Тя съдържа последния низ, който е бил намерен от регулярен израз. В повечето случаи вие ще искате да видите това, което сте намерили и да го съхраните някъде. Това става благодарение на обратните референции. Ето пример за използването на обратни референции: CODE
Позволено ви е да използвате, толкова променливи за обратни референции, колкото ви трябват.Единственото условие да не се опитвате да ги променяте по време на работата на програмата, тъй като те са само за четене. CODE
Много често ще ви се налага да правите операциите съединяване и разделяне на низове. Да използваме за това шаблони е възможно, но е неудобно. Perl обаче ни пердоставя две функции за тази цел - split (за разделяне на низове и съхранението на отделните елементи в масив) и join (за съединяване на списък в низ). Ето пример: CODE
Трудното става, когато се наложи да разделим низ, който отделните думи не са разделени с празни символи, а със запетаи да кажем. В този случай разгледаната проста форма на split няма да ни помогне. За наша радост split е по-сложен от показаното - той приема шаблон за дефиниране на разделителите. Всъщност простата форма е еквивалентна на split(/s+/,$_). Тук на мястото на s+ може да поставите какъвто си искате шаблон. Следващият атрибут е променливата върху, която се прилага функцията. По същият начин може да дефинирате и разделител, който да използвате при съидиняването на списък в низ - join("",@array) CODE
Накрая ще ви отбележа някои от обичайните грешки, които се допускат при писане на регулярни изрази. Например a*b*c ще съвпадне с всеки низ, който съвпада с всеки знак нула пъти. Ето още няколко такива клопки: * Забравяне да се групира: Bam{2} ще съвпадне с Bamm, докато /(Bam){2}/, ще съвпадне с BamBam. Същото важи и за алтернативата:/Simple|on/ ще съвпадне със "Simple" и с "on", докато Sim(ple)|on ще съвпадне със "Simple" и с "Simon". * Грешно поставяне на котвите: ^ стои в началото , а $ в края. Знакът за долар на всяко друго място, кара perl да се опита да интерполира променливата. * Забравяне да се промени интерпретацията на специалните знакове: Ето за кои знакове трябва да внимавате: . * ? + [] () {} ^ $ и . * Започване на броенето не от нула: На първия елемент от масива се дава индекс нула. * Броене от нула: Всяко правило си има изключения. Първата променлива за обратна референция е $1, а не $0. Това са основите на регулярните изрази. За да се научите да пишете регулярни изрази трябва да пишете регулярни изрази...много. Следващата глава, ще се научите да работите с файлове.
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||









