Navigace

Hlavnφ menu

 

Perl-compatible regulßrnφ v²razy v PHP - dalÜφ u₧iteΦnΘ funkce

Ve vÜech p°edchßzejφcφch Φlßncφch jsme si p°i p°edvßd∞nφ jednotliv²ch regulßrnφch v²raz∙ vystaΦili pouze se dv∞ma funkcemi. V tomto Φlßnku se proto seznßmφme s n∞kolika dalÜφmi u₧iteΦn²mi funkcemi pro prßci s Perl-compatible regulßrnφmi v²razy v PHP. Vzhledem k tomu, ₧e vÜe, co se t²Φe konstrukce regulßrnφch v²raz∙ samotn²ch, bylo ji₧ probrßno, budu se p°i popisovßnφ jednotliv²ch p°φklad∙ v∞novat hlavn∞ funkcφm sam²m.

Funkce preg_match_all()

Funkce preg_match_all($re,$str,$matched) funguje velmi podobn∞ jako funkce preg_match($re,$str,$matched) (viz subv²razy a zp∞tnß reference) jen s tφm rozdφlem, ₧e najde v °et∞zci $str vÜechny °et∞zce, kterΘ odpovφdajφ regulßrnφmu v²razu $re (zatφmco preg_match($re,$str,$matched) najde jen prvnφ v²skyt). Funkce preg_match_all() vracφ poΦet °et∞zc∙, kterΘ odpovφdajφ celΘmu regulßrnφmu v²razu.

P°φklad demonstrujφcφ rozdφlnΘ chovßnφ funkcφ:

$re="/(CZK|EUR|USD) (\d+)/";
$str="CZK 1200 nebo EUR 40 nebo USD 50";
$result1=preg_match($re,$str,$matched1); //vrßtφ int(1)
$result2=preg_match_all($re,$str,$matched2); //vrßtφ int(3)

Pole $matched1 pak bude (var_dump($matched1)):

array(3) {
  [0]=>
  string(8) "CZK 1200"
  [1]=>
  string(3) "CZK"
  [2]=>
  string(4) "1200"
}

Pole $matched2 pak bude (var_dump($matched2)):

array(3) {
  [0]=>
  array(3) {
    [0]=>
    string(8) "CZK 1200"
    [1]=>
    string(6) "EUR 40"
    [2]=>
    string(6) "USD 50"
  }
  [1]=>
  array(3) {
    [0]=>
    string(3) "CZK"
    [1]=>
    string(3) "EUR"
    [2]=>
    string(3) "USD"
  }
  [2]=>
  array(3) {
    [0]=>
    string(4) "1200"
    [1]=>
    string(2) "40"
    [2]=>
    string(2) "50"
  }
}

Index 0 v obou polφch ($matched1 a $matched2) oznaΦuje, ₧e se jednß o °et∞zec (respektive °et∞zce) odpovφdajφcφ celΘmu regulßrnφmu v²razu. ╪et∞zce odpovφdajφcφ jednotliv²m subv²raz∙m jsou indexovßny Φφsly jednotliv²ch subv²raz∙ (v naÜem p°φpad∞ 1, 2). V poli $matched2 je ka₧d² prvek ($matched2[0], $matched2[1], $matched2[2]) sßm o sob∞ polem. Indexy v t∞chto polφch odpovφdajφ (t°em) jednotliv²m nalezen²m °et∞zc∙m.

Pokud se vßm nelφbφ, ₧e takto vzniklΘ dvojrozm∞rnΘ pole $matched2 je indexovßno nejd°φve podle subv²raz∙ a a₧ potΘ podle nalezen²ch °et∞zc∙, m∙₧ete toto chovßnφ zm∞nit pomocφ p°φznaku PREG_SET_ORDER, kter² se funkci p°edß jako jejφ Φtvrt² argument.

Pou₧ijeme-li stejnou hodnotu prom∞nn²ch $re a $str jako v p°ikladu v²Üe a zavolßme funkci preg_match_all($re, $str, $matched3, PREG_SET_ORDER), tato funkce vytvo°φ pole $matched3:

array(3) {
  [0]=>
  array(3) {
    [0]=>
    string(8) "CZK 1200"
    [1]=>
    string(3) "CZK"
    [2]=>
    string(4) "1200"
  }
  [1]=>
  array(3) {
    [0]=>
    string(6) "EUR 40"
    [1]=>
    string(3) "EUR"
    [2]=>
    string(2) "40"
  }
  [2]=>
  array(3) {
    [0]=>
    string(6) "USD 50"
    [1]=>
    string(3) "USD"
    [2]=>
    string(2) "50"
  }
}

Funkce preg_grep()

Funkce preg_grep($re, $strings) mß dva argumenty (parametry). Prvnφm argumentem je regulßrnφ v²raz, druh²m argumentem je pole °et∞zc∙. Funkce vracφ pole slo₧enΘ z prvk∙ (p∙vodnφho pole $strings), kterΘ odpovφdajφ regulßrnφmu v²razu $re.

╪ekn∞me, ₧e mßme pole obsahujφcφ hesla u₧ivatel∙ a chceme z nich vybrat pouze hesla delÜφ ne₧ 5 znak∙.

$re="/\w{6,}/";
$strings=array("uu123","jaro","abcdefg","hohoho");
$result=preg_grep($re,$strings);

V²slednΘ pole $result bude obsahovat po₧adovanß hesla:

array(2) {
  [2]=>
  string(7) "abcdefg"
  [3]=>
  string(6) "hohoho"
}

Funkce preg_replace_callback()

Pomocφ funkce preg_replace() jsme mohli zam∞nit °et∞zec odpovφdajφcφ regulßrnφmu v²razu za jin² °et∞zec (s vyu₧itφm °et∞zce "zachycenΘho" pomocφ regulßrnφho v²razu Φi subv²razu). S pomocφ preg_replace_callback() dokß₧eme jeÜt∞ mnohem vφce. ╪et∞zec odpovφdajφcφ regulßrnφmu v²razu m∙₧eme toti₧ nahradit °et∞zcem, kter² zφskßme jako nßvratovou hodnotu vlastnφ (u₧ivatelsky definovanΘ) funkce. Tato naÜe funkce p°itom m∙₧e pracovat s °et∞zcem, kter² odpovφdß regulßrnφmu v²razu (Φi subv²razu).

╪ekn∞me, ₧e mßme k dispozici seznam dvojcifern²ch Φφsel, kterß p°edstavujφ roky (respektive letopoΦty). NaÜφm ·kolem je p°evΘst letopoΦty dvojcifernΘ na letopoΦty Φty°cifernΘ, a to tak, ₧e do roku 29 vΦetn∞ budou p°evßd∞ny na letopoΦty ve tvaru 20XX a od roku 30 (vΦetn∞) v²Üe budou p°evßd∞ny na letopoΦty ve tvaru 19XX. Asi tuÜφte, ₧e naÜe (u₧ivatelsky definovanß) funkce bude mφt za ·kol prßv∞ rozhodnout zda doplnit "19" Φi "20".

function letopocet($rok)
{
  if($rok[0]<30)
  {
    $prefix="20";}
  else
  {
    $prefix="19";
  };
  return $prefix.$rok[0];
};

$re="/\d{2}/";
$function_name="letopocet"; //nßzev u₧ivatelskΘ funkce
$str="12, 91, 45, 29, 30, 01";
$result=preg_replace_callback($re,$function_name,$str);

V prom∞nnΘ $result pak zφskßme °et∞zec 2012, 1991, 1945, 2029, 1930, 2001.

CelΘ to funguje tak, ₧e funkce preg_replace_callback() zavolß u₧ivatelsky definovanou funkci (jejφ₧ nßzev obdr₧φ jako hodnotu svΘho druhΘho argumentu) a tΘ p°edß pole obsahujφcφ °et∞zec, kter² odpovφdß regulßrnφmu v²razu (p°φpadn∞ tΘ₧ °et∞zce, kterΘ odpovφdajφ jednotliv²m subv²raz∙m). ╪et∞zec, kter² odpovφdß celΘmu regulßrnφmu v²razu, je v poli pod indexem 0. U₧ivatelskß funkce zpracuje n∞jak²m zp∙sobem p°edanß data a poÜle svou nßvratovou hodnotu zp∞t funkci preg_replace_callback(). Toto se provede pro ka₧dΘ nahrazenφ. V okam₧iku, kdy jsou vÜechna nahrazenφ provedena, m∙₧e funkce preg_replace_callback() skonΦit a vrßtit svou nßvratovou hodnotu (tedy cel² upraven² °et∞zec).

Funkce preg_split()

Funkce preg_split($re, $str), rozd∞lφ °et∞zec $str na Φßsti, kterΘ vrßtφ jako pole °et∞zc∙. Jako odd∞lovaΦ se pou₧ije °et∞zec odpovφdajφcφ regulßrnφmu v²razu $re. Op∞t mal² p°φklad:

$re="/[,; ]+/";
$str="honza@inmail.cz;jarda@jarda.com filip@mudrc.cz ,; tomas@svaty.cz";
$result=preg_split($re,$str);

V naÜem p°φpad∞ regulßrnφmu v²razu popisujφcφmu odd∞lovaΦ odpovφdß (neprßzdn²) °et∞zec slo₧en² ze znak∙ Φßrka, st°ednφk a mezera v libovolnΘm po°adφ a poΦtu. A tak pole $result bude obsahovat ji₧ jen jednotlivΘ e-mailovΘ adresy:

array(4) {
  [0]=>
  string(15) "honza@inmail.cz"
  [1]=>
  string(15) "jarda@jarda.com"
  [2]=>
  string(14) "filip@mudrc.cz"
  [3]=>
  string(14) "tomas@svaty.cz"
}

Funkce preg_quote()

Tuto funkci m∙₧eme oznaΦit jako pomocnou. Nezpracovßvß toti₧ urΦit² °et∞zec pomocφ regulßrnφho v²razu, ale pom∙₧e nßm p°i tvorb∞ regulßrnφho v²razu. N∞kdy toti₧ pot°ebujeme vytvo°it regulßrnφ v²raz a₧ za b∞hu naÜeho skriptu a tak nem∙₧eme "ruΦn∞" oÜet°it metaznaky (doplnit p°ed n∞ \), jestli₧e chceme potlaΦit jejich specißlnφ funkΦnost.

Za b∞hu skriptu nßm vznikne nap°φklad °et∞zec a+b=c, kter² chceme pou₧φt jako regulßrnφ v²raz. Pokud zavolßme preg_quote("a+b=c"), funkce vrßtφ °et∞zec a\+b\=c.

Nesmφme zapomenout, ₧e cel² regulßrnφ v²raz je uzav°en v odd∞lovaΦφch (delimiters), m∞li bychom proto takΘ zajistit, aby znaku, kter² pou₧φvßme jako odd∞lovaΦ (v naÜem p°φpad∞ pou₧φvßme obyΦejnΘ lomφtko /) takΘ p°edchßzelo zp∞tnΘ lomφtko \. Proto₧e funkce nem∙₧e sama o sob∞ v∞d∞t, jak² odd∞lovaΦ pou₧φvßme, p°edßme ji tuto informaci v nepovinnΘm druhΘm argumentu.

Pokud tedy zavolßme nap°φklad preg_quote("a+b/c=d","/"), funkce vrßtφ °et∞zec a\+b\/c\=d. Jak m∙₧ete vid∞t, znak \ je i p°ed znakem =, aΦkoli = nenφ metaznak. Funkce toti₧ dopl≥uje zp∞tnß lomφtka i p°ed znaky, kterΘ mohou tvo°it specißlnφ konstrukce (nap°φklad tvrzenφ o nßsledujφcφm a p°edchßzejφcφm). Zp∞tn²m lomφtkem jsou proto dopln∞ny znaky ., \, +, *, ?, [, ^, ], $, (, ), {, }, =, !, <, >, | a :.

Pecka, Miroslav (17. 5. 2005)