Reguliariosios išraiškos ir šablonai |
PERL kalbos pirminė paskirtis buvo palengvinti ir išplėsti ataskaitų kūrimo galimybes UNIX operacinėje sistemoje, todėl natūralu, kad ši kalba turi gerai išvystytas tekstų apdorojimo funkcijas. UNIX operacinėje sistemoje tekstinės informacijos apdorojimui paprastai naudojamos tokios komandas kaip sed, awk, grep, cut. Šių komandų paskirtis yra ribota, todėl norint gauti sudėtingą ataskaitą, rašomi pakankamai dideli ir sudėtingi shell script'ai. Taigi čia į pagalbą ateina PERL kalbos reguliarios išraiškos bei šablonai.
Reguliariosios išraiškos tai taisyklių rinkiniai, aprašantys tekstinį šabloną, pagal kurį randamas reikalingas tekstas ar fragmentas. Papraščiausios reguliariosios išraiškos tai literalų eilutės. Sudėtingesnėse reguliariose išraiškose naudojami metasimboliai, kurie apibrėžia galimus ieškomo teksto ar fragmento variantus.
Pačias paprasčiausias reguliariasias išraiškas sudaro vienas paprastas simbolis. Paprastas simbolis reguliarioje išraiškoje reiškia pats save ir papildomai neinterpretuojamas.
Metasimboliai tai spec.simboliai, turintys tam tikrą reikšmę reguliariose išraiškose. Metasimboliai gali būti naudojami vietoj vieno simbolio arba jų grupės.
Simboliai bei metasimboliai, priklausantys reguliariajai išraiškai, atskiriami / / ir formuoja eilutės paieškos šabloną. Pavyzdžiui:
/Perl/ - atitinka visos eilutės,
kuriose yra žodis Perl
/ab*c/ - atitinka visos eilutės,
kuriose yra simboliai abc (b simbolių gali būti bet koks skaičius)
Jei šabloną atitinka tekstas eilutėje, tuomet grąžinama reikšmė "true" arba "1", priešingu atveju grąžinama reikšmė "false" arba "0".
PERL metasimboliai ir jų prasmė
Toliau panagrinėsime reguliariose išraiškose naudojamus pagrindinius metasimbolius.
Metasimbolis | Reikšmė | Pavyzdžiai |
\ |
Metasimbolio maskavimas. Naudojant "\" , metasimbolis interpre-tuojamas kaip paprastas simbolis, t.y. jam nesuteikiama speciali reikšmė. | "\*" interpretuojamas, kaip * |
. | Atitinka bet kokį simbolį, išskyrus naujos eilutės simbolį, nors nau-dojant su raktu s , įtraukiamas ir naujos eilutės simbolis. | /Per./ |
| | Skiria alternatyvas, panašiai kaip loginė operacija arba. | /a|b|c/ |
() | Grupavimo metasimboliai. Jie paprastai naudojami apibrėžiant kartojimą (žr.žemiau). | /And(y|rew)/ - bus ieškoma Andy arba Andrew |
[] | Nurodo, kad šablone naudojamas vienas iš simbolių esančių skliaustuose. | [A-Za-z] bet kuri abėcėlės raidė; [^0-9] bet kuris
simbolis, išskyrus skaičių. "^" laužtiniuose skliaustuose reiškia neigimą. |
\t | Tabuliacija (HT, TAB) | |
\n | nauja eilutė (LF, NL) | |
\r | "karietėlės" grąžinimas (CR) | |
\f | puslapio prasukimas (FF) | |
\a | "Skambutis" | |
\e | Escape | |
\033 | Simbolis su nurodyta reikšme (aštuntainėje sistemoje) | |
\x1B | Simbolis su nurodyta reikšme (šešioliktainėje sistemoje) | |
\c[ | Control-simbolis | |
\l | nurodo, kad sekanti raidė turi būti mažoji | |
\u | nurodo, kad sekanti raidė turi būti didžioji | |
\L | nurodo, kad tolesnės raidės nuo \L iki \E turi būti mažosios | |
\U | nurodo, kad tolesnės raidės nuo \U iki \E turi būti mažosios | |
\E | keitimo pabaiga | |
\Q | cituoti metasimbolius iki \E literaliai | |
\w | Žodis ar simbolis (raidės, skaičiai ir "_" ženklas). \w iš esmės tas pats kaip [a-zA-Z_0-9] | |
\W | neŽodis ar nežodžiams naudojamas simbolis.
\W tas pats kaip [^a-zA-Z_0-9] |
|
\s | Tuščia vieta (tarpas, tabuliacija). \s tas pats kaip [\t\n\r\f] | |
\S | Netuščia vieta. \S tas pats kaip [^\t\n\r\f] | |
\d | Skaitmuo t.y. tas pats kaip [0-9] | |
\D | Ne skaitmuo t.y. tas pats kaip [^0-9] | |
\0 | simbolis, turinti kodą 0 | |
\skaičius | grupavimo konstrukcijos t.y. skliaustų ( ) numeris reguliarioje išraiškoje (numeruojama nuo 1) | /fred(.)barney\1/ - atitinka fredXbarneyX /a(.)b(.)c\2d\1/ - atitinka axbycydx |
Vietą nurodantys metasimboliai
Žemiau išvardinti simboliai nurodo ieškomo teksto vietą eilutėje. Dažniausiai naudojami ^ ir $ metsimboliai reiškiantys atitinkamai eilutės pradžią ir pabaigą.
Metasimbolis | Reikšmė | Pavyzdžiai |
^ | Eilutės pradžią reiškiantis metasimbolis | |
$ | Eilutės pabaigą reiškiantis metasimbolis, jei jis randasi šablono pa-baigoje. Kitoje vietoje esantis metasimbolis nurodo, kad į šabloną reikia įterpti kintamojo reikšmę. | |
\b | Žodžio riba (vieta, kur prasideda arba baigiasi žodis) | |
\B | ne žodžio riba (visos vietos, išskyrus tas, kur prasideda arba baigiasi žodis) | |
\A | Eilutės pradžia | |
\Z | Eilutės pabaiga arba vieta prieš naują eilutę | |
\z | Tik eilutės pabaiga | |
\G | Vieta, kur baigė prieš tai veikusi m//g komanda |
Pasikartojimo nurodymas reguliariose išraiškose
Žemiau išvardinti simboliai pasako, kad prieš juos buvusi reguliarioji išraiška (t.y. iš kairės) gali pasikartoti eilutėje tam tikrą kiekį kartų.
Metasimbolis | Reikšmė | Pavyzdžiai |
* | kartoti 0 ir daugiau kartų | /.*/ - bet kuri eilutė |
+ | kartoti 1 ir daugiau kartų | /.+/ - bet kuri netuščia eilutė |
? | kartoti 0 arba 1 kartą | /(array)?/ - žodis array bus 1 arba 2 kartus eilutėje |
{n} | kartoti tiksliai n kartų | /[0-9]{3}/ - bet koks tri-ženklis skaičius |
{n,} | kartoti n ir daugiau kartų | /r{5,}/ |
{n,m} | kartoti nuo n iki m kartų | /r{2,5}/ |
Kintamieji, susiję su reguliariomis išraiškomis
Jei eilutėje buvo rastas tekstas, atitinkantis šabloną,
tai likusi eilutės dalis, neatitikusi šablono, yra priskiriama specialiems
kintamiesiems. Šabloną atitikęs tekstas taip pat priskiriamas specialiajam
kintamajam.
Metasimbolis | Reikšmė |
$& | Eilutės dalis, atitikusi šabloną |
$` | Eilutės dalis, likusi prieš šabloną atitikusią eilutės dalį |
$' | eilutės dalis, likusi už šabloną atitikusios eilutės dalies |
Pavyzdys
$_ = "tai yra testinis
pavyzdys";
/tes.*nis/; # atitinka žodį "testinis"
# $` reikšmė "tai yra "
# $& reikšmė
"testinis"
# $' reikšmė
"pavyzdys"
Jei reguliarioje išraiškoje naudojamas grupavimas, tai radus eilutėje tekstą, kuris atitiko šabloną, sukuriami kintamieji $1, $2, $3 ir t.t., kurie turi tas pačias reikšmes kaip ir \1, \2, \3 ir t. t. Pavyzdžiui:
$_ = "this is a test";
/(\w+)\W+(\w+)/; # šį šabloną atitinka pirmi du žodžiai, todėl
# $1 dabar
yra "this", o $2 turi reikšmę
"is"
Išplėstinės reguliariosios išraiškos
Norint išplėsti šablonų panaudojimo galimybes, buvo praplėsta reguliariųjų išraiškų sintaksė įvedant (?.....) konstrukciją. Simbolis, einantis po ?, apibrėžia funkciją, kuri turi būti atliekama. Šiuo metu naudojama apie dešimt išplėstinių reguliariųjų išraiškų konstrukcijų. Panagrinėkime dažniausiai naudojamas konstrukcijas.
(?#text) tekstas
esantis po "#" ir
iki " )" laikomas
komentaru ir ignoruojamas. Pavyzdžiui
/Perl(?#
ieškome žodžio Perl)/.
(?:pattern) grupavimas, kaip ir "(...)" atveju, tačiau nesukuriami kintamieji $1, $2 ir t. t. (žr. aukščiau). Pavyzdžiui /(?:Perl|perl)/.
(?=pattern) sekantis teksto fragmentas turi atitikti pattern. Tai reiškia, kad prieš šią konstrukciją turi būti šablonas, o tik po jo (?=pattern). Pavyzdžiui, /\w+(?=\t)/ atitinka žodį, po kurio iš kart eina tabuliacija. Be to tabuliacija nepriskiriama $& kintamajam.
(?!pattern) ši konstrukcija reiškia, jog sekantis teksto fragmentas neturi atitikti pattern. Pavyzdžiui, /foot(?!ball)/ atitinka bet kurį žodį ar jo fragmentą foot, išskyrus football. ball nepriskiriamas $& kintamajam.
(?<=pattern) konstrukcija reiškianti, jog prieš buvęs teksto fragmentas turi atitikti pattern. Pavyzdžiui, /(?<=bad)boy/ atitinka žodį boy, jei prieš jį buvo bad. Be to bad nepriskiriamas $& kintamajam.
(?<!=pattern) konstrukcija reiškianti, jog prieš buvęs teksto fragmentas neturi atitikti pattern. Pavyzdžiui, /(?<!=bad)boy/ atitinka bet kurį žodį boy, jei prieš jį nebuvo bad. bad nepriskiriamas $& kintamajam.
(?>pattern) atitinka eilutę, kurioje pattern yra nurodytoje pozicijoje.
Naudojant išplėstines reguliariasias išraiškas,
galima naudoti ir paiešką modifikuojančius raktus t.y. (?imsx-imsx). Jie dar
vadinami modifikatoriais. Jei prieš raides i, m, s, x
rašomas -, tuomet modifikatorius atšaukiamas.
Pavyzdžiui /(?ix) perl #
ignoruojamos didž.-maž. raidės ir bei galimi tarpai šablone/
Žemiau pateikti modifikatorių paaiškinimai.
Modifikatorius | Reikšmė |
i | Paieška ignoruojant didžiasias ir mažasias raides. |
m | Eilutė traktuojama kaip multi-eilutė, kurią sudaro keletas eilučių atskirtų naujos eilutės simboliu. |
s | Eilutė traktuojama kaip viena eilutė. Metasimbolis . reiškia bet kokį simbolį, tame tarpe ir naujos eilutės simbolį. |
x | Leidžiama šablonuose naudoti komentarus ir tarpo simbolius. |
Veiksmai naudojant reguliariasias išraiškas
Išsiaiškinę reguliariųjų išraiškų formavimo principus, pereikime prie sekančio etapo, t. y. reguliariųjų išraiškų panaudojimo Perl skriptuose. Taigi reguliariosios išraiškos paprastai naudojamos norint atlikti paieškos operaciją, pakeitimo ar transliteracijos veiksmus. Panagrinėkime kiekvieną iš šių operacijų.
PAIEŠKA
Sintakė
m/pattern/[g i m o s x]
Paieškos operacija atlieka šabloną atitinkančio teksto paiešką. Operacijos rezultatas gali būti reikšmė 1 (true) arba tuščia eilutė (false). Pagal nutylėjimą paieška vykdoma eiltutėje, priskirtoje specialiajam kintamajam $_. Naudojant pririšimo operatorius =~ ir !~ galima atlikti paiešką ir kitiems kintamiesiems priskirtose eilutėse. Operatoriai =~ ir !~ skiriasi tuo, kad grąžina skirtingas logines reikšmes. Pavyzdžiui:
$var =
Mano batai buvo du;
$var =~ m/^Man./; #vykdome paiešką kintamajam $var priskirtoje
eilutėje
#ir gražinama true, nes randamas žodis Mano
$var !~ m/^Man./ #false, nes randamas žodis Mano
Raktai g
i m o s x modifikuoja paieškos operacijas. Žemiau pateiktas jų
aprašymas.
Raktai | Reikšmė |
g | Globali paieška t.y. bus rasti visi teksto fragmentai eilutėje, atitinkantys paieškos šabloną. Pagal nutylėjimą paieška baigiama suradus pirmąjį atitikmenį. |
i | Paieška ignoruojant didžiasias ir mažasias raides |
m | Eilutė traktuojama kaip multi-eilutė, kurią sudaro keletas eilučių atskirtų naujos eilutės simboliu |
o | Kintamieji, esantys šablone, naudojami tik vieną kartą. |
s | Eilutė traktuojama kaip viena eilutė. Metasimbolis . reiškia bet kokį simbolį, tame tarpe ir naujos eilutės simbolį |
x | Leidžiama šablonuose naudoti komentarus ir tarpo simbolius. |
Pavyzdžiai
#Ignoruojamos
didžiosios bei mažosios
raidės
print "Ar pratesti darbą? ";
if (<STDIN> =~ m/^y]/i) {
# tikrinama ar įvedimas pradedamas y simboliu?
print "Tai šaunu\n! ";
}
#Globali paieška masyvo ir skaliariniame kontekste
$str="abaabbaaabbb";
@result = $str =~ m/a+b+/g; #masyvo
kontekstas globalioje paieškoje
print "\@result = @result\n";
@result = $str =~ m/(a+)(b+)/g;
#masyvo kontekstas globalioje paieškoje
print "\@result = @result\n";
print "Skaliarinis kontekstas\n";
while ($result=$str =~m/ m/(a+)(b+)/g; { #skaliarinis kontekstas globalioje
paieškoje
print "result=$result \n";
}
#Paieška
naudojant skirtingus raktus
@pattnlist = ("a+", "b+", "c+", "d+"); #masyvas, apibrėžiantis paieškas
foreach $pattn (@pattnlist) {
$line = <STDIN>;
$line =~ m/$pattn/o
#dėl rakto o, naudojamas tik a+
šablonas
print "pattn=$pattn \$& = $&\n";
}
PAKEITIMAS
Sintakė
s/pattern/replacement/[e g i m o s x]
Pakeitimo operacija s/pattern/replacement/ atlieka šabloną pattern atitinkančio teksto paiešką ir, jei jis randamas, pakeičiamas tekstu replacement. Operacijos grąžinama reikšmė atliktų pakeitimų skaičius arba tuščia eilutė, jei nebuvo atliktas nei vienas pakeitimas. Pagal nutylėjimą paieška vykdoma eiltutėje, priskirtoje specialiajam kintamajam $_ . Naudojant pririšimo operatorius =~ ir !~ galima atlikti paiešką ir kitiems kintamiesiems priskirtose eilutėse, pavyzdžiui:
$var =~ s/pattern/replacement/[e g i m o s x]
Raktai g i m o s x reiškia tą patį kaip ir atliekant paieškos operaciją, o raktas e pasako, kad keičiamąjį tekstą replacement pirmiausiai reikia interpretuoti kaip PERL išraišką, o tik po to atlikti pakeitimus.
Pavyzdžiai
$_=
"foot fool buffoon";
s/foo/bar/g; #dabar $_ yra "bart
barl bufbarn"
$_=
"this is a test";
s/(w+)/<$1>/g;
# dabar $_ yra "<this> <is>
<a > <test>"
$_=
"Hello world";
$new = "Goodbye";
s/hello/$new/;
# dabar $_ yra "Goodbye world"
$str
= "abaabbaaabbb";
$result=$str =~s[(a+b+)]<length($1)>ge;
print "result=$result new str=$str\n";
#result=3 new str=246
TRANSLITERACIJA
Sintakė
tr/searchlist/replacement/[c d s]
Transliteracijos operacija keičia kiekvieną simbolį iš sąrašo searchlist į atitinkamą simbolį iš pakeitimų sąrašo replacement. Pagal nutylėjimą pakeitimai atliekami eiltutėje, priskirtoje specialiajam kintamajam $_ . Naudojant pririšimo operatorius =~ ir !~ galima atlikti paiešką ir kitiems kintamiesiems priskirtose eilutėse, pavyzdžiui:
$var =~ tr/searchlist/replacement/[c d s]
Simbolių sąrašai searchlist ir replacement gali būti pateikiami kaip atskirai išvardinti simboliai ar simbolių diapazonai. Pavyzdžiui:
$str =~ tr/A-Z/a-z/ #didžiosios raidės keičiamos mažosiomis.
Žemiau pateiktas raktų, naudojamų transliteracijos operacijose, aprašymas.
Raktai | Reikšmė |
c | Paieškos sąrašas searchlist praplėčiamas per visą ASCII lentelę |
d | Naikinami visi simboliai iš sarašo searchlist, kurie neturi atitinkamo elemento replacement sąraše. |
s | Visi simboliai, kurie buvo pakeisti į vienodą simbolį, keičiami vieninteliu jo egzemplioriumi. |
Pavyzdžiai
$count = $str =~ tr/\000/ /c #suskaičiuojamas simbolių skaičius eilutėje.
$str =~ tr/\200-\377/
/cs #bet kuri simbolių seka nuo ASCII kodo 128 iki 255
#keičiama vieninteliu tarpo simboliu
$_ = "fred and barney";
tr/fb/bf/;
# $_ dabar "bred and farney"
tr/abcde/ABCDE/;
# $_ dabar "BrED AnD fArnEy"
tr/a-z/A-Z/;
# $_ dabar "BRED AND FARNEY"
$count = tr/A-Z//;
# $_ nepakeistas, o $count lygus 13
$count1 = tr/A-Z//c;
# $_ nepakeistas, o $count1 lygus 2 (suskaičiuoti
# neraidiniai simboliai t.y. tarpai)
tr/A-Z/x/;
# $_ dabar "xxxx xxx xxxxxx"
tr/a-z/_/c;
# $_ dabar "xxxx_xxx_xxxxxx"
t.y. (non-letters => _)
Naudingos eilučių apdorojimo funkcijos
Žemiau pateikiamos dažniausiai naudojamos PERL funkcijos, skirtos darbui su eilutėmis.
Funkcija | Sintaksė | Reikšmė |
chop() | chop($str) | Pašalina eilutės paskutinį simbolį. Funkcija grąžina pašalintą simbolį. |
lenght() | lenght(str) | Grąžinamas eilutės str ilgis. |
lc() | lc(expression) | Gražinama eilutė mažosiomis raidėmis |
uc() | uc(expression) | Gražinama eilutė didžiosiomis raidėmis |
lcfirst() | lcfirst(expression) | Pirmas eilutės simbolis keičiamas į mažąją raidę |
ucfirst() | ucfirst(expression) | Pirmas eilutės simbolis keičiamas į didžiąją raidę |
split() | split([/pattern/[,expr[,limit]]] | Pagal šabloną sudalina eilutę į laukus |
join() | join(expression,list) | Sujungia laukus (masyvo narius) į vieną eilutę. |
index() | index(str,substr[,position]) | Eilutėje str ieškoma eilutė substr nuo pozicijos position bei grąžinama rasta pozicija. Jei substr nerasta - gražinama f-jos reikšmė -1 |
rindex() | rindex(str,substr[,position]) | Eilutėje str ieškoma eilutė substr iki pozicijos position bei grąžinama rasta pozicija. Jei substr nerasta - gražinama f-jos reikšmė -1 |
substr() | substr(str,offset[,lenght[,repl]]) | Iš eilutės str paimama lenght ilgio subeilutė, esanti į dešinę nuo offset pozicijos. Jei užduotas parametras repl, tai subeilutė keičiama į repl. |
eval() | eval{expression} | Funkcija parametrą expression vykdo, kaip PERL programinį kodą. Jei expression nenurodytas, naudojamas kintamasis $_. Jei įvyko klaida, kintamajame $@ talpinamas klaidos pranešimas. |
Pavyzdžiai
#Pozicijos paieška
eilutėje
$person = "barney";
$where = index("fred barney",$person); #
$where lygus 5
$where = index("hello world","l");
# $where lygus 2 (pirmasis l)
$where = index("hello world","l",3);
# $where lygus 3
$w = rindex("hello world","he");
# $w lygus 0
$w = rindex("hello world","l");
# $w lygus 9 (dešiniausias l eilutėje)
$w = rindex("hello world","xx");
# $w lygus -1 (nes nerastas)
#Eilutės dalies
paėmimas arba pekeitimas
$hello = "hello, world!";
$grab = substr($hello, 3, 2);
# $grab lygus "lo"
$grab = substr($hello, 7, 100);
# $grab lygus "world!"
substr($hello, 0, 5) = "hi";
# $hello dabar "hi world!"
#Vykdoma PERL
kodas, nuskaitytas iš STDIN
print "code line: ";
chop($code = <STDIN>);
eval $code; die "eval: $@" if $@;
# PERL kodas vykdomas, jei nėra klaidų
#Eilutės
skaidymas ir sujungimas
$line = "merlyn::118:10:Randal:/home/merlyn:/usr/bin/perl";
@fields = split(/:/,$line);
# skaidoma $line, ties rastais :
#
# dabar @fields yra
("merlyn","","118","10","Randal","/home/merlyn","/usr/bin/perl")
#
$outline = join(":", @fields);
#atstatoma eilutė $line naujame kintamajame
$outline