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:]]+)\.([[:alpha:]]{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 ;).
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