Не сте регистриран! Регистрирайте се БЕЗПЛАТНО, за да използвате услугите на сайта!

   Рубрики
 
 
 
 

 Форуми
» SEO и оптимизация
» Всичко за PHP и Perl
» Всичко за C, C++ и .NET
» Всичко за Java и JSP
» Всичко за SQL и MySQL
» Всичко за XHTML и CSS
» Презентация на сайтове
 PERL - ШЕСТА ЧАСТ
  1. PERL - ШЕСТА ЧАСТ
deam0n
     
Автор  deam0n (20.02.2005 14:35)  съобщение до автора
Погледнат  3749 пъти  добави към любими
Оценка  добави коментар
Гласове  1  изпрати на приятел
Коментари  (0)  абонирай се за Perl
    Страница 1 / 1

 



Регулярните изрази ни позволяват да търсим шаблони в нашите данни. Използвайки правилата на регулярните изрази можем да използваме една единствена стойност (шаблон), за да опишем търсеното от нас в по-общи граници. Регулярните изрази са много голяма тема и тази глава ще ви запознае само с принципите на тяхното писане. Ако искате да вникнете в тънкостите на регулярните изрази пишете програми и експериментирайте.
   Може да употребите регулярните изрази за три различни неща :съвпадение, заместване и транслитерация. Операцията по съвпадение използва оператора m/шаблон/, който връща истина или лъжа, в зависимост от това дали шаблона е намерен или не. Операцията заместване, замества един израз с друг и използва оператора s/шаблон/заместващ шаблон/. Транслитерацията замества един или повече символа с други и използва оператора tr/символ/заместващи символи/. Всички те работят с променливата по подразбиране $_. По късно ще разберете как те може да се използват и върху други променливи. Ако мястото на шаблона е празно Perl използва последния дефиниран шаблон. Това е причината, понякога да виждате на пръв поглед една конструкция със странно условие - if // {...}.
   Всеки регулярен израз позволява да се използват алтернативни разделители на шаблона вместо //. Това може да са {},||,[],!! и т.н. Ето пример и за ползата от това:

CODE
1
2
3
4
5
#Чрез използване на //
m//root/home/file.txt/
#Ето и същото обаче с алтернативен
  1. разделител
m{/root/home/file.txt}

Разбира се нищо не ви пречи да поставите шаблона в променлива, която след това да поставите в оператора за съвпадение :

CODE
1
2
my $path = '/root/home/file.txt';
m/$path/;

Ако изберете за алтернативен разделител апострофи, то ще загубите интерполацията на променливите в шаблона. Ето и просто използване на регулярен израз:

CODE
1
2
3
4
5
6
7
8
9
10
#!/usr/bin/perl
#ex33.plx
use warnings;
use strict;
$_ = "Some text to search";
print "Ok.I found it.n" if m/text/;

>
perl ex33.plx
Ok
.I found it.
>

Тъй като оператора m// е най-често използвания, то perl позволява той да се изпуска.

CODE
1
2
3
4
#Пълен запис
print "Ok.I found it.n" if m/text/;
#Съкратен запис
print "Ok.I found it.n" if /text/;

Оператора за съвпадение притежава няколко допълнителни опции, които разширяват неговата функционалност:

CODE
1
2
3
4
5
6
7
8
9
10
11
12
13
Опция      Действие
g
    Чрез тази опция правите глобално търсене в целия низ. Като резултат връща списък с намерените съвпадения.
i
    Тази опция игнорира големината на символите в низа.
m
    Тази опция казва на
Perl, че низа се състои от множество реда.
o
    Ако включите тази опция
perl ще изчисли израза само веднъж.
s
    При включването на тази опция
perl третира низа като един ред.
x
    Позволява използването на коментари и празни редове в шаблоните.

Тези опции се поставят след крайния раделител на шаблона. Ето пример за използването на опцията i :

CODE
1
2
3
4
5
6
7
8
9
10
#!/usr/bin/perl
#ex34.plx
use warnings;
use strict;
$_ = "SOME TEXT TO SEARCH";
print "Ok.I found it.n" if /text/i;

>
perl ex34.plx
Ok
.I found it.
>

Оператора за заместване се използва за промяна на низовете. Той изисква две операнда - s/a/z/. Това ще замести първата срещната буква a с буквата z. И тук може да използвате променливи в ролята на шаблон или заместващ шаблон.

CODE
1
2
3
4
5
6
7
8
9
10
11
12
13
#!/usr/bin/perl
#ex35.plx
use warnings;
use strict;
$_ = "Some text to search";
my $oldtext = "serach";
my $newtext = "substitute";
my $result = s/$oldtext/$newtext/;
print $_,"n";

>
perl ex35.plx
Some text to
substitute
>

И при този оператор може да използвате алтернативни разделители. Подобно на оператора за съвпадение и s///, позволява използването на опции. Те са същите като и преди, но с една допълнително. Това е опцията "/е". Тя казва на perl да изчисли шаблона за заместване като израз. Това ще ви позволи да намери всички числа в низа и да ги умножите с някакъв процент, например. Ако използвате тази опция, интерполацията на променливи се включва даже и да използвате апострофи. Разгледайте следния ред:

CODE
1
$result = s/sometext/`dir`/е;


Това, което прави този ред е да замести sometext с изхода на досовската команда dir.
   Оператора за транслитерация, който свързва знаковете в двата си аргумента един по един и да използва тези двойки за заместване на отделни знакове в дадения низ. Например tr/abc/xyz/ ще замести а с x, b с y и c с z. Ето пример за използването му:

CODE
1
2
3
4
5
6
7
8
9
10
11
#!/usr/bin/perl
#ex36.plx
use warnings;
use strict;
$_ = "2011064";
tr/0123456789/abcdefghij/;
print $_,"n";

>
perl ex36.plx
cabbage

>

Ако в дясната част е празна (tr/abc//), то транслитерация няма да се осъществи и низа няма да се промени. Това може да се промени ако се използва опцията /d. Чрез нея казваме на perl да изтрие знака от лявата част, който няма свързващ знак отдясно.
   До тук работихме само с променливата $_. Ами ако искаме да работим с други променливи? Perl разбира се не ни ограничава и затова добавя два нови оператора =~ и !~. Те позволяват да свържем регулерните изрази към променлива различна от $_. Оператора =~ връща 1 ако шаблона е намерен в низа и недефинирана стойност ако не е. Обратно !~ връща 1 ако шаблона не е намерен и недефинирана стойност ако е намерен в низа.Ето малък пример демонстриращ действието им:

CODE
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#!/usr/bin/perl
#ex37.plx
use warnings;
use strict;
my $scalar = "The root has many leaves";
my $match = $scalar =~ m/root/;
my $substitution = $scalar =~ s/root/tree/;
my $translate = $scalar =~ tr/h/H/;

print("$match = $matchn");
print("$substitution = $substitutionn");
print("$translate = $translaten");
print("$scalar = $scalarn");

>
perl ex37.plx
$match = 1
$substitution = 1
$translate = 2
$scalar = THe tree Has many leaves
>

Дотук разгледаните шаблони, не показват пълната мощ на регулярните изрази. Затова сега ще засегнем темата, как се създават шаблоните. Това става благодарение на т.нар. метазнакове. Това са знаци, които имат значение различно от литералното и това е подразбиращото им значение в регулярните изрази. Ако искате даден метазнак да има своето литерално значение в регулярен израз, то пред него трябва да сложите префикса "".
    Регулярните изрази донякъде работят като кавички. Така, че вътре в тях се извършва интерполация. Важно е да знаете, че интерполацията е само на едно ниво т.е. ако имате променлива $scalar и тя съдържа низ, с друга променлива, интерполация се извършва само на променливата $scalar. Всеки символ в регулярния израз съвпада само със себе си. Изключение правят символите $, @ , & и метазнаковете. Ако искате да използвате някои от тях в буквалното си значение е необходимо да сложите пред него обратно наклонена черта. Ето и таблица с метазнаковете:

CODE
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
Мета- знакове      Действие
^     Указва търсенето в шаблона да е само в началото на низа. Това е една от двете т.нар. котви.Ако е използвана опцията
/m, то шаблона се търси в началото на всеки ред.
.     Съвпада със всичко освен нов ред, докато не е включена опцията
/s. В този случай съвпада и с нов ред.
$     Втората котва. Търси шаблона само в края на реда на низа. Ако е включена опцията
/m , то шаблона се търси в крач на всеки ред.
|     Това е знак за алтернатва. Например шаблона m
/a|b/,ще търси или а или b.
  •     Този метазнак указва, че това което търсим трябва да се среща един или повече пъти, но може и нито веднъж.
+     Този метазнак указва, че това което търсим трябва да се среща един или повече пъти.
?     Указва, че това което търсим трябва да се среща
0 или 1 път.В добавка с +,_,? или {n,m}, изключва "лакомото" поведение на регулярния израз, като съвпада с най-малкия възможен низ.
()     Променя изпълнението на регулярния израз.
(?...)     Показва, че следва разширен синтаксис.
{n,m}     Показва колко пъти трябва да се повтори елемента, който търсим.{n,} показва, че трябва да се повтори не - малко от n пъти.m е маскималния брой повторения.
[]     С тези скоби се образува знаков клас. Например m/[abc]/ ще е истина ако в низа има a,b или с.
     Това е управляващ символ. С негова помощ може да използвате метазнаковете с тяхното буквално значение. Н
aпример $ e символа $.
&
#65533;nnn     Всеки осмичен байт.
a     Аларма
A     Означава началото на низа. Не се влияе от опцията /m.
b     Означава граница на дума. Граница на дума е точката между буквените знакове (w) и небуквените такива (W). Ако се използва в знаков клас означава символа "backspace".
B     Съвпада с граница на нещо различно от дума.
cn     Всякакъв контролен знак.
d     Това съвпада с единичен символ от 0 до 9.
D     Съвпада с единичен не-цифров знак.
e     Escape
E     Прекъсва действието на U и L.
f     Нова страница на принтера
l     Променя следващия знак на малък.
L     Променя знаковете след това на малки до края на регулярния израз или до срещането на E.
n     Нов ред.
Q     Изключва специалното значение на метазнаковете. Това е в сила до края на регулярния израз или до срещане на
/Е.Интерполацията не се спира.
r     Връщане на "каретката" (carrige return)
s     Съвпада е единичен празен символ.
S     Съвпада с единичен не-празен символ.
t     Табулация.
u     Променя следващият символ на голям (uppercase)
U     Променя знаковете след това на големи до края на регулярния израз или до срещането на E.
v     Вертикална табулация.
w     Единичен знак за "дума".Тук се включва и долното тире.
W     Знак, различен от знака за "дума"
xnn     Шестнайсетичен знак.
Z     Означава края на низа. Не се влияе от опцията /m.
$     Знака за долар.
@     Амперсанд.

Тази голяма таблица не трябва да ви притеснява. Повечето от показаните метасимволи се използват много рядко.
   Знакови класове: Квадратните скоби се използват за създаването на знакови класове. Той служи за съвпадение с определен тип знак. Например, за да създадете шаблон, който да съвпадне с всяко число може да използвате следното: 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
1
m/w/;

 Ако искате да получите съвпадение с дума с един или два символа:

CODE
1
m/w|ww/;

По този начин може да добавите колкото си искате символа, но Perl ни предоставя по-добър начин:

CODE
1
m/w+/;

   Това ще съвпадне с дума с един или повече буквени символа. Ако стойноста на $_ е "ААА ВВВ", то горния шаблон ще съвпадне с "ААА". Това ще ви позволи да разберете дали в низа има дума, но не и каква е тя. Тук идват на помощ обратните референции.

CODE
1
m/(w+)/;

 По този начин казвате на Perl да пази стойноста на намереното в променливата $1. Когато пишете шаблони, много често ще използвате знаковите класове. Например [0123456789] ще дефинира знаков клас за десетичните цифри, а [0-9a-f] ще дефинира знаков клас за шестнайсетичните цифри. Трябва да имате впредви, че знаков клас от вида [a-9] не е валиден и perl ще прекъсне програмата с грешка. И тук може да използвате интерполация за създаване на знакови класове. Ето пример:

CODE
1
2
3
4
5
6
7
8
9
10
11
#!/usr/bin/perl
#ex38.plx
use warnings;
use strict;
$_ = "AAA BBB";
my $pattern = "ADE";
print "matchedn" if m/[$charList]/;

>
perl ex38.plx
matched

>

Представете си, че ви се наложи да търсите даден символ, но не знаете колко пъти. Perl ни предоставя няколко различни метазнакове за повторения. Това са *, +, {n}, {n,} и {n,m}. Ако търсите дума, но не знаете от колко символа се състои, можете да напишете следното:

CODE
1
m/w+/;

Това ще съвпадне с "ААА", "ВВВВВ", но не и с " ВВВ" или " ". В случай, че имате в началото празен(и) символ(и) трябва да използвате метазнака за празен символ s последван от метазнака *.

CODE
1
m/s*w+/;

Ако решите да търсите символа, определен брой пъти може да напишете следното:

CODE
1
2
$_ = "AA AB AC AD AE";
m/(w+s+){5}/;

Това ще съвпадне само ако низа съдържа пет думи. Това е така, защото търсим неопределен брой букви, последвани от неопределен брой празни символи, всичко това повторено пет пъти. Както казах по-горе, машината за регулярни изрази е лакома. Метазнаковете * и + ще съвпаднат с възможно най-голям брой символи:

CODE
1
2
3
4
5
6
7
8
9
10
#!/usr/bin/perl
#ex39.plx
use warnings;
use strict;
$_ = '/user/Jackie/temp/names.dat';
m/.*/;
print $&;

>
perl ex39.plx
/
user/Jackie/temp/names.dat>

  Ако искате да избегнете лакомото поведение може да използвате ?:

CODE
1
2
3
4
5
6
7
8
9
10
#!/usr/bin/perl
#ex40.plx
use warnings;
use strict;
$_ = '/user/Jackie/temp/names.dat';
m/.*?/;
print $&;

>
perl ex40.plx
/>

Може би се чудите какво е $&. Ами това е една от служебните променливи на perl. Тя съдържа последния низ, който е бил намерен от регулярен израз.
   В повечето случаи вие ще искате да видите това, което сте намерили и да го съхраните някъде. Това става благодарение на обратните референции. Ето пример за използването на обратни референции:

CODE
1
2
3
4
5
6
7
8
9
10
11
#!/usr/bin/perl
#ex41.plx
use warnings;
use strict;
$_ = "AAA BBB ccC";
m/(w+)/;
print("$1n");

>
perl ex41.plx
AAA

>

Позволено ви е да използвате, толкова променливи за обратни референции, колкото ви трябват.Единственото условие да не се опитвате да ги променяте по време на работата на програмата, тъй като те са само за четене.

CODE
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#!/usr/bin/perl
#ex42.plx
use warnings;
use strict;
$_ = "AAA BBB ccC";
while (m/(w+)/g) {
print("$1n");
}

>
perl ex42.plx
AAA
BBB
ccC

>

Много често ще ви се налага да правите операциите съединяване и разделяне на низове. Да използваме за това шаблони е възможно, но е неудобно. Perl обаче ни пердоставя две функции за тази цел - split (за разделяне на низове и съхранението на отделните елементи в масив) и join (за съединяване на списък в низ). Ето пример:

CODE
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#!/usr/bin/perl
#ex43.plx
use warnings;
use strict;
$_ = "There is a big dog here";
my @splitedString = split;
foreach (@splitedString){
print $_,"n";
}
my $newstring = join(@splitedString);
print $newstring,"n";

>
perl ex43.plx
There
is
a
big
dog
here
There is a big
dog here
>

Трудното става, когато се наложи да разделим низ, който отделните думи не са разделени с празни символи, а със запетаи да кажем. В този случай разгледаната проста форма на split няма да ни помогне. За наша радост split е по-сложен от показаното - той приема шаблон за дефиниране на разделителите. Всъщност простата форма е еквивалентна на split(/s+/,$_). Тук на мястото на s+ може да поставите какъвто си искате шаблон. Следващият атрибут е променливата върху, която се прилага функцията. По същият начин може да дефинирате и разделител, който да използвате при съидиняването на списък в низ - join("",@array)

CODE
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#!/usr/bin/perl
#ex44.plx
use warnings;
use strict;
my $oldstring = "one,two,three,four,five";
print "Before split:$oldstringn";
my @temparray = split(/,/,$oldstring);
my $newstring = join("",@temparray);
print "After join:$newstringn";

>
perl ex44.plx
Before
split:one,two,three,four,five
After
join:onetwothreefourfive
>

Накрая ще ви отбележа някои от обичайните грешки, които се допускат при писане на регулярни изрази. Например a*b*c ще съвпадне с всеки низ, който съвпада с всеки знак нула пъти. Ето още няколко такива клопки:

    * Забравяне да се групира: Bam{2} ще съвпадне с Bamm, докато /(Bam){2}/, ще съвпадне с BamBam. Същото важи и за алтернативата:/Simple|on/ ще съвпадне със "Simple" и с "on", докато Sim(ple)|on ще съвпадне със "Simple" и с "Simon".
    * Грешно поставяне на котвите: ^ стои в началото , а $ в края. Знакът за долар на всяко друго място, кара perl да се опита да интерполира променливата.
    * Забравяне да се промени интерпретацията на специалните знакове: Ето за кои знакове трябва да внимавате: . * ? + [] () {} ^ $ и .
    * Започване на броенето не от нула: На първия елемент от масива се дава индекс нула.
    * Броене от нула: Всяко правило си има изключения. Първата променлива за обратна референция е $1, а не $0.

   Това са основите на регулярните изрази. За да се научите да пишете регулярни изрази трябва да пишете регулярни изрази...много. Следващата глава, ще се научите да работите с файлове.



   


Ключови думи: perl програмиране шаблон code код


Още уроци от тази рубрика


 
  • Подобни теми от myLinks
 

 1 посетител чете този урок (0 потребители и 1 гост)  
Активни потребители: ---
   
  

Еmail  
 

 

 
  • Интересно от Софтуер
 



IT-PLACE.NET © 2004 - 2008