Hlavní navigace

Regulární výrazy v PHP: Funkce

13. 11. 2003
Doba čtení: 6 minut

Sdílet

Výsledky domácího úkolu, podrobný popis funkcí Ereg a Ereg_Replace a zas ne taková spousta užitečných rad :) To je druhý díl seriálu o regulárních výrazech v PHP.

Začínáme

Někdo mi vyčetl, že v minulém díle jsem nevyjmenoval dva důležité metaznaky, takže někdo byl docela zmaten. Hodně rychle: – je metaznak, který umožňuje označit rozsah, to znamená že a-z jsou všechna malá písmena anglické abecedy. Metaznak ^, pokud není na začátku řetězce, znamená negaci.

Domácí úkol :)

Začneme domacím úkolem z prvního dílu :) Správná odpověď: Maska (^([[:alnum:]]+)@([[­:alnum:]]+)\.([[:al­pha:]]{2,4})$) je nepoužitelná v tom, že:

1a) V první části nejsou obsazeny znaky jako _ nebo . (tečka) apod. V některých případech může být použito dokonce i plus.
1b) V první části nemůžou být dvě tečky za sebou.
1c) Uživatel nemůže začínat tečkou. 2a) V části domény II. řádu opět neobsahuje pomlčku. Při použití domky III. řádu je potřeba i tečka.
2b) Tečkou to však nesmí začínat a nesmí být dvě za sebou.
3a) V části domény I. řádu by měla mít maximálně čtyři znaky. Něco jsem slyšel i o delších doménách, ale nevím dopodrobna o co jde, tak mě prosím nekamenujte :)
3b) Zde nepotřebujeme tečku pro domény, jako je např. com.uk apod., protože se část před tečkou automaticky připíše k doméně II. řádu.

Dalo by se jít i daleko dál do brutusu, ale je to už docela zbytečné :) a asi by to po nějakém čase ani nebylo aktuální. Jak má vypadat správná maska pro emailovou adresu? Odpověd zní:

^[a-zA-Z0-9_\+-]+(\.[a-zA-z0-9_\+-]+)*@[a-zA-Z0-9-]+ (\.[a-zA-Z0-9-]+)*\.[a-zA-Z]{2,4}$

Konečně dosaďme masku do skriptu:

<?
# overeni spravnosti emailu v PHP(2) - ROOT.cz
# skript predpoklada register_globals = on
# v konfiguracnich souborech php
# promenna s emailem je $email

// definujeme masku
$maska = '^[a-zA-Z0-9_\-\+]+ (\.[a-zA-z0-9_\-\+]+)*@[a-zA-Z0-9\-]+ (\.[a-zA-Z0-9\-]+)*\.[a-zA-Z]{2,4}$';

// definujeme funkci
function overmail($a)
{
global $maska;

if (EregI($maska ,$a))
// rika, ze mail je platny
return "email ".$a." je platny";

else
// vraci chybu
return "email ".$a." je neplatny :P";
}

// zavola funkci a vypise jako html stranku :)
echo "<html>\n<body>\n".overmail($email)."\n</body>\n</html>";
?>

Další zajímavé řešení je na ZENDu, kde to ale nedělají podle jedné masky, takže je to docela zbytečně složité (rozdělování řetězce a až potom vyhodnocování). Funguje to pomalu, ale dobře :).

Úvod do funkcí

Základní funkce pro pracování s regulárními výrazy jsou Ereg a Ereg_Replace. První slouží k porovnávání textu vzhledem k masce. Druhá nahradí v textu část, která vyhovuje masce, jiným textem. Obě funkce mají svoje odrůdy EregIa EregI_Replace, které nerozlišují velikost písmen

Ereg

Ereg jsem již popsal v minulém dílu, kde jsem také nastínil, že u funkce Ereg je nepovinný třetí parametr. Ten načte vyhovující podvýrazy do pole. Pozor! Jednotlivé podvýrazy se načítají do pole od prvku 1, tj. $pole[1], nikoliv od nuly. Do nultého prvku pole se uloží celá část řetězce vyhovující masce :). Teď si napíšeme jednoduchou funkci, která pomocí této vlastnosti funkce Ereg rozkouskuje email na login, doménu 2. řádu a doménu 1. řádu.

<?
# kouskovani emailu v PHP - ROOT.cz
# register_globals = on
# promenna s emailem je $email

// maska s podvyrazy
$maska = '^([a-zA-Z0-9_\-\+]+ (\.[a-zA-z0-9_\-\+]+)*)@([a-zA-Z0-9\-]+ (\.[a-zA-Z0-9\-]+)*)\.([a-zA-Z]{2,4})$';

function overmail($a)
{
global $maska;

if (!Ereg($maska, $a, $pole))
return "Email je neplatny :P";
else
return
"Uzivatel: ".$pole[1]."<br>\n
Domena: ".$pole[3]."<br>\n
Koncovka: ".$pole[5]."<br>\n";
}

// zavola funkci a vypise html
echo "<html>\n<body>\n".overmail($email)."\n</body>\n</html>";
?>

Ereg_Replace

Tak a teď přišla řada na Ereg_Replace. Funkce má tři parametry – první je maska regulárky, druhý parametr definuje text, kterým budeme nahrazovat část textu vyhovující regulárnímu výrazu, a třetí je text, který budeme upravovat. Ukážeme si to na příkladu, kde zpácháme zločin měnění textových smajlů za grafické. Text :), :-) a :o) vyměníme za a :(, :-( a :o( za . Závorku na konci smajlu zkvantifikujeme plusem, aby se zaměnoval i smajl :-)))). Masky a náhrady uložíme do polí, doplňování pak bude lehčí. Pokud k masce nebude žádná náhrada, text se nezmění.


<?
# obrazkovani smajliku 1 - ROOT.cz

// definujeme text
$text = "Zdravim :-) :o))) :)<br>Loucim:-(( :(( :o(";

// masky a jejich nahrady

$maska[1] = ':\-)+';
$maska[2] = ':o)+';
$maska[3] = ':)+';
$maska[4] = ':\-\(+';
$maska[5] = ':o\(+';
$maska[6] = ':\(+';

$nahrada[1] = '<img src="hehe.png">';
$nahrada[2] = '<img src="hehe.png">';
$nahrada[3] = '<img src="hehe.png">';
$nahrada[4] = '<img src="nehehe.png">';
$nahrada[5] = '<img src="nehehe.png">';
$nahrada[6] = '<img src="nehehe.png">';

// funkce pro filtrovani
function filtr($a)
{
global $maska, $nahrada;

for($i=1; $i<=Count($maska); $i++)
$a = Ereg_Replace($maska[$i], $nahrada[$i], $a);

return $a;
}

// filtrace textu
$text = filtr($text);

// vypsani html
echo "<html>\n<body>\n".$text."\n</body>\n</html>";
?>



Ereg_Replace a metaznak \\

Na čtvrtém příkladu si ukážeme další kejkle s funkcí Ereg_Replace. Jelikož v předchozím případě jsme znásilnili html obrázky, lidé používající textové prohlížeěe (já) (pozn. red.: A já! :) –Johanka) nemají žádnou šanci smajlíky uvidět. Napravíme to atributem alt. Využijeme mnou dosud zatajovaný metaznak \\číslo, který zastupuje jednotlivé podvýrazy podobně, jako to dělá Ereg, jenom k tomu nepoužívá pole :), ale tento metaznak. A podobně jakou u Ereg se do 0 uloží celý řetězec vyhovující regexpu (masce) a teprve pak se číslují jednotlivé podvýrazy od jedné.

Jasně, ten alt atribut můžeme vepsat nahrubo do proměnné $nahrada, ale to bychom ztratili počet závorek a typ nosíku :). Do $nahrady tedy původního smajlíka vypíšeme metaznakem \\ . Nemusíme masku uzávorkovat, ale použijeme \\0. Skript tedy bude vypadat následovně.

<?
# obrazkovani smajliku 2 - ROOT.cz

// definujem text
$text = "Jirka pouziva Linux -> :-)) :)\n<br>Bill pouziva domaci avivaz -> :(( :o((((";

// masky a jejich nahrady

$maska[1] = ':\-)+';
$maska[2] = ':o)+';
$maska[3] = ':)+';
$maska[4] = ':\-\(+';
$maska[5] = ':o\(+';
$maska[6] = ':\(+';

$nahrada[1] = '<img src="hehe.png" alt="\\0">';
$nahrada[2] = '<img src="hehe.png" alt="\\0">';
$nahrada[3] = '<img src="hehe.png" alt="\\0">';
$nahrada[4] = '<img src="nehehe.png" alt="\\0">';
$nahrada[5] = '<img src="nehehe.png" alt="\\0">';
$nahrada[6] = '<img src="nehehe.png" alt="\\0">';

// funkce pro filtrovani
function filtr($a)
{
global $maska, $nahrada;

for($i=1; $i<=Count($maska); $i++)
$a = Ereg_Replace($maska[$i], $nahrada[$i], $a);

return $a;
}

// filtrace textu
$text = filtr($text);

// vypsani html
echo "<html>\n<body>\n".$text."\n</body>\n</html>";
?>


Na obrázcích vidíme, jak se skript chová v obrázkové Mozille a v textovému Lynxu.

Končíme :)

Ták a teď jeden rébus :) Co dělá druhý skript nepřesně? Nemyslím nic takového, jako že v názvu domény nemůžou být dvě pomlčky za sebou :) Napovím, že je to někde za zavináčem a kolem tečky :)

Příště se podíváme na ještě pokročilejší funkce, jako jsou SQL_Regcase nebo Split a SplitI (rozdělování řetězců), které si porovnáme s textovou funkcí Explode a nakonec zjistíme, že jsou ve velké části případů úplně na ;).

root_podpora

Linky:

ZEND > Ověřování emailu
PHP Manual
PHP Manual > Funkce pro regulární výrazy POSIX-Extended
PHP Manual > Ereg
PHP Manual > Ereg_Replace
PHP Manual > EregI
PHP Manual > EregI_Replace

Soubory:

Domácí úkol
Použité skripty (včetně domácího úkolu :)

Byl pro vás článek přínosný?