
W pewnym stadium zaawansowania wyrażenia regularne stają się potężnym narzędziem każdego programisty PHP (i nie tylko). A to dlatego, że pozwalają na wykonywanie operacji, których często nie sposób dokonać w prosty sposób przy pomocy standardowych funkcji zawartych w tym języku. Walidacja zawartości zmiennych, czy podmienianie specyficznej części ich zawartości – na to pozwalają wyrażenia regularne. 15-ście przykładowych, najbardziej niezbędnych dla każdego web developera, skompletowałem w dalszej części artykułu. Do Waszej dyspozycji oddaję także prosty serwis sprawdzający poprawność wprowadzanych wzorców.
1. Walidacja adresu e-mail opartego na hoście
Wzorzec:
/^([a-z0-9]{1})([^\s\t\.@]*)((\.[^\s\t\.@]+)*)@([a-z0-9]{1})((([a-z0-9-]*[-]{2})|([a-z0-9])*|([a-z0-9-]*[-]{1}[a-z0-9]+))*)((\.[a-z0-9](([a-z0-9-]*[-]{2})|([a-z0-9]*)|([a-z0-9-]*[-]{1}[a-z0-9]+))+)*)\.([a-z0-9]{2,6})([.]?)$/Diu
Opis:
Wyrażenie ma za zadanie sprawdzać, czy wprowadzony przez użytkownika adres e-mail ma poprawną formę. Aby test zakończył się sukcesem muszą zostać spełnione następujące warunki:
- nazwa użytkownika musi zaczynać się od znaku litery lub cyfry, nie może zawierać spacji, tabulatorów, aty, za to mogą się znajdować w nim kropki, pod warunkiem, że nie występują jedna, po drugiej,
- po nazwie użytkownika musi pojawiać się znak małpy,
- domena, podobnie jak nazwa użytkownika, musi rozpoczynać się od litery, bądź cyfry, po czym do znaków dozwolonych dochodzą - oraz ., pod warunkiem, że pierwszy z wcześniej wymienionych znaków nie znajduje się na początku lub na końcu nazwy subdomeny (wyjątkiem są dwa myślniki na jej końcu odpowiadające często prefiksom xn--), a drugi nie jest poprzedzany swoim odpowiednikiem. TLD może mieć długość od dwóch do sześciu znaków,
- domena może być zakończona kropką,
- rozwiązanie nie sprawdza jak długi jest wprowadzony adres e-mail.
Strona testowa:
Tutaj.
Tekst spełniający warunki:
2.a_a-d@n-do.x-d.pl
Tekst nie spełniający warunków:
2.a_a-d@n-do.x-d.v-.pl (część domeny kończąca się nieprawidłowym znakiem)
Uwagi:
Jeżeli rozwiązanie w jakimkolwiek stopniu zawiedzie można pokusić się o użycie wyrażenia z ostatniej aktualizacji pliku logical_filters.c ze źródeł PHP.
Rozwiązanie oparte o wyrażenie regularne:
$email = trim('adres@domena.pl');
if ( !preg_match('/^([a-z0-9]{1})([^\s\t\.@]*)((\.[^\s\t\.@]+)*)@([a-z0-9]{1})((([a-z0-9-]*[-]{2})|([a-z0-9])*|([a-z0-9-]*[-]{1}[a-z0-9]+))*)((\.[a-z0-9](([a-z0-9-]*[-]{2})|([a-z0-9]*)|([a-z0-9-]*[-]{1}[a-z0-9]+))+)*)\.([a-z0-9]{2,6})([.]?)$/Diu', $email) )
{
print 'Nieprawidłowy adres e-mail';
}
Rozwiązanie oparte o filter_var (PHP >= 5.2):
$email = trim('adres@domena.pl');
if ( (bool)filter_var($email, FILTER_VALIDATE_EMAIL) === false )
{
print 'Nieprawidłowy adres e-mail';
}
2. Walidacja adresu e-mail opartego na hoście lub IPv4 serwera
Wzorzec:
/^([a-z0-9]{1})([^\s\t\.@]*)((\.[^\s\t\.@]+)*)@((([a-z0-9]{1})((([a-z0-9-]*[-]{2})|([a-z0-9])*|([a-z0-9-]*[-]{1}[a-z0-9]+))*)((\.[a-z0-9](([a-z0-9-]*[-]{2})|([a-z0-9]*)|([a-z0-9-]*[-]{1}[a-z0-9]+))+)*)\.([a-z0-9]{2,6})([.]?))|((\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])))$/Diu
Opis:
Wyrażenie ma za zadanie sprawdzać, czy wprowadzony przez użytkownika adres e-mail ma poprawną formę. Aby test zakończył się sukcesem muszą zostać spełnione warunki z poprzedniego punktu oraz:
- po znaku @ musi się pojawić opisany już wcześniej prawidłowo sformowany host lub adres IPv4 serwera w postaci czterech, dziesiętnych oktetów.
Strona testowa:
Tutaj.
Tekst spełniający warunki:
2.a_a-d@64.64.100.100
Tekst nie spełniający warunków:
2.a_a-d@64.64.256.100 (trzeci oktet jest po za zakresem)
Uwagi:
Jeżeli rozwiązanie w jakimkolwiek stopniu zawiedzie można pokusić się o użycie wyrażenia z ostatniej aktualizacji pliku logical_filters.c ze źródeł PHP.
Rozwiązanie oparte o wyrażenie regularne:
$email = trim('adres@85.64.100.100');
if ( !preg_match('/^([a-z0-9]{1})([^\s\t\.@]*)((\.[^\s\t\.@]+)*)@((([a-z0-9]{1})((([a-z0-9-]*[-]{2})|([a-z0-9])*|([a-z0-9-]*[-]{1}[a-z0-9]+))*)((\.[a-z0-9](([a-z0-9-]*[-]{2})|([a-z0-9]*)|([a-z0-9-]*[-]{1}[a-z0-9]+))+)*)\.([a-z0-9]{2,6})([.]?))|((\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])))$/Diu', $email) )
{
print 'Nieprawidłowy adres e-mail';
}
Rozwiązanie oparte o filter_var (PHP >= 5.2):
$email = trim('adres@domena.pl');
if ( (bool)filter_var($email, FILTER_VALIDATE_EMAIL) === false )
{
print 'Nieprawidłowy adres e-mail';
}
3. Prosta weryfikacja adresu URL
Wzorzec:
/^(http|ftp)([s]{0,1}):\/\/([a-z0-9]{1})((([a-z0-9-]*[-]{2})|([a-z0-9])*|([a-z0-9-]*[-]{1}[a-z0-9]+))*)((\.[a-z0-9](([a-z0-9-]*[-]{2})|([a-z0-9]*)|([a-z0-9-]*[-]{1}[a-z0-9]+))+)*)(\.([a-z0-9]{2,6})){0,1}((:[0-9]){0}|(:[1-9]{1}[0-9]*))\//iu
Opis:
Zweryfikować, czy użytkownik wprowadził adres URL, wg wzoru:
protokół://adres_serwera:port/
- dozwolone protokoły: http, https, ftp, ftps,
- adres serwera w formie serwera lokalnego, subdomen, domeny i rozszerzenia,
- port jest opcjonalny,
- dalsze wprowadzone dane (jak Query String) nie są sprawdzane,
- konstrukcja jest przeznaczona do sprawdzanie adresów opartych na IPv4.
Strona testowa:
Tutaj.
Tekst spełniający warunki:
http://m1chu.eu/
Tekst nie spełniający warunków:
htt://adres.com/temp/ (nieprawidłowy schemat)
Rozwiązanie oparte o wyrażenie regularne:
$url = trim('http://m1chu.eu');
if ( !preg_match('/^(http|ftp)([s]{0,1}):\/\/([a-z0-9]{1})((([a-z0-9-]*[-]{2})|([a-z0-9])*|([a-z0-9-]*[-]{1}[a-z0-9]+))*)((\.[a-z0-9](([a-z0-9-]*[-]{2})|([a-z0-9]*)|([a-z0-9-]*[-]{1}[a-z0-9]+))+)*)(\.([a-z0-9]{2,6})){0,1}((:[0-9]){0}|(:[1-9]{1}[0-9]*))\//iu', $url) )
{
print 'Nieprawidłowy adres URL';
}
4. Wycinanie hosta z portem z adresu URL
Wzorzec:
/^(http|ftp)([s]{0,1}):\/\/((.*)\.[a-z0-9]{2,6}|((\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5]))){0,1}((:[0-9]){0}|(:[1-9]{1}[0-9]*))\//iu
Opis:
Pobrać host wraz z portem (jeżeli został podany) z URI. Pozostałe zasady są tożsame z wymienionymi w poprzednim punkcie.
Strona testowa:
Tutaj.
Tekst spełniający warunki:
http://m1chu.eu:80/ (zwróci: m1chu.eu:80)
Tekst nie spełniający warunków:
htt://adres.com/temp/ (nieprawidłowy schemat)
Rozwiązanie oparte o wyrażenie regularne:
$url = trim('ftps://stro.eu:1000/file.exe');
if ( preg_match('/^(http|ftp)([s]{0,1}):\/\/((.*)\.[a-z0-9]{2,6}|((\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5]))){0,1}((:[0-9]){0}|(:[1-9]{1}[0-9]*))\//iu', $url, $matches) )
{
// $matches[3] - nazwa serwera z domeną lub adres IPv4
// $matches[10] - port
print $matches[3] . ':' . $matches[10];
}
5. Sprawdzanie adresu IP (protokół IPv4)
Wzorzec:
/^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])$/Du
Opis:
Wykryć poprawność wprowadzonego w formie dziesiętnych oktetów IP (w wersji czwartej protokołu).
Strona testowa:
Tutaj.
Tekst spełniający warunki:
0.0.0.0
Tekst nie spełniający warunków:
101.256.0.1 (drugi oktet poza zakresem)
Rozwiązanie oparte o wyrażenie regularne:
$ipv4 = trim('192.168.0.1');
if ( !preg_match('/^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])$/Du', $ipv4) )
{
print 'Nieprawidłowy adres IPv4';
}
Rozwiązanie oparte o filter_var (PHP >= 5.2):
$ipv4 = trim('192.168.0.1');
if ( (bool)filter_var($ipv4, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) === false )
{
print 'Nieprawidłowy adres IPv4';
}
6. Sprawdzamy adres IP z wykluczeniem puli prywatnych adresów (protokół IPv4)
Wzorzec:
/^([1-9]{1}[1-9]{0,1}|1\d([1-6]{1}|[8-9]{1})|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-4])$/Du
Opis:
Wykryć poprawność wprowadzonego IP (w wersji czwartej protokołu) z wykluczeniem części prywatnych i zastrzeżonych pul. Metoda nie dotyczy masek podsieci. Objęte wyjątki:
- 10.0.0.0 – 10.255.255.255,
- 0.0.0.0 – 0.255.255.255,
- 255.255.255.255,
- 127.0.0.0 – 127.255.255.255.
Strona testowa:
Tutaj.
Tekst spełniający warunki:
192.168.0.136
Tekst nie spełniający warunków:
0.0.0.0 (adres prywatny)
Uwagi:
Stosując funkcję ze zbioru filter_* odrzucone zostaną wszystkie zakresy adresów prywatnych i zastrzeżonych (np. 255.255.255.x).
Rozwiązanie oparte o wyrażenie regularne:
$ipv4 = trim('68.78.205.0');
if ( !preg_match('/^([1-9]{1}[1-9]{0,1}|1\d([1-6]{1}|[8-9]{1})|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-4])$/Du', $ipv4) )
{
print 'Nieprawidłowy adres IPv4';
}
Rozwiązanie oparte o filter_var (PHP >= 5.2):
$ipv4 = trim('68.78.205.0');
if ( (bool)filter_var($ipv4, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 | FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE) === false )
{
print 'Nieprawidłowy adres IPv4';
}
7. Sprawdzamy adres IP (protokół IPv6 i IPv4)
Wzorzec:
/^((([0-9A-Fa-f]{1,4}:){7}(([0-9A-Fa-f]{1,4})|:))|(([0-9A-Fa-f]{1,4}:){6}(:|((25[0-5]|2[0-4]\d|[01]?\d{1,2})(\.(25[0-5]|2[0-4]\d|[01]?\d{1,2})){3})|(:[0-9A-Fa-f]{1,4})))|(([0-9A-Fa-f]{1,4}:){5}((:((25[0-5]|2[0-4]\d|[01]?\d{1,2})(\.(25[0-5]|2[0-4]\d|[01]?\d{1,2})){3})?)|((:[0-9A-Fa-f]{1,4}){1,2})))|(([0-9A-Fa-f]{1,4}:){4}(:[0-9A-Fa-f]{1,4}){0,1}((:((25[0-5]|2[0-4]\d|[01]?\d{1,2})(\.(25[0-5]|2[0-4]\d|[01]?\d{1,2})){3})?)|((:[0-9A-Fa-f]{1,4}){1,2})))|(([0-9A-Fa-f]{1,4}:){3}(:[0-9A-Fa-f]{1,4}){0,2}((:((25[0-5]|2[0-4]\d|[01]?\d{1,2})(\.(25[0-5]|2[0-4]\d|[01]?\d{1,2})){3})?)|((:[0-9A-Fa-f]{1,4}){1,2})))|(([0-9A-Fa-f]{1,4}:){2}(:[0-9A-Fa-f]{1,4}){0,3}((:((25[0-5]|2[0-4]\d|[01]?\d{1,2})(\.(25[0-5]|2[0-4]\d|[01]?\d{1,2})){3})?)|((:[0-9A-Fa-f]{1,4}){1,2})))|(([0-9A-Fa-f]{1,4}:)(:[0-9A-Fa-f]{1,4}){0,4}((:((25[0-5]|2[0-4]\d|[01]?\d{1,2})(\.(25[0-5]|2[0-4]\d|[01]?\d{1,2})){3})?)|((:[0-9A-Fa-f]{1,4}){1,2})))|(:(:[0-9A-Fa-f]{1,4}){0,5}((:((25[0-5]|2[0-4]\d|[01]?\d{1,2})(\.(25[0-5]|2[0-4]\d|[01]?\d{1,2})){3})?)|((:[0-9A-Fa-f]{1,4}){1,2})))|(((25[0-5]|2[0-4]\d|[01]?\d{1,2})(\.(25[0-5]|2[0-4]\d|[01]?\d{1,2})){3})))(%.+)?$/Du
Opis:
Wykryć poprawność wprowadzonego IP (w wersji szóstej i czwartej protokołu).
Strona testowa:
Tutaj.
Tekst spełniający warunki:
fe80:0:0:0:0204:61ff:254.157.241.86
Tekst nie spełniający warunków:
2001:::db8:: (błędna notacja)
Uwagi:
Stosując funkcję ze zbioru filter_* odrzucone zostaną wszelkie adresy IPv4. W przedstawionym wyrażeniu regularnym adresy z tej wersji są akceptowane zarówno występując samotnie, jak i w postaci sekwencji czterech ostatnich bajtów w IPv6 (np. :247.125.68.4).
Rozwiązanie oparte o wyrażenie regularne:
$ipv6 = trim('fe80::204:61ff:fe9d:f156');
if ( !preg_match('/^((([0-9A-Fa-f]{1,4}:){7}(([0-9A-Fa-f]{1,4})|:))|(([0-9A-Fa-f]{1,4}:){6}(:|((25[0-5]|2[0-4]\d|[01]?\d{1,2})(\.(25[0-5]|2[0-4]\d|[01]?\d{1,2})){3})|(:[0-9A-Fa-f]{1,4})))|(([0-9A-Fa-f]{1,4}:){5}((:((25[0-5]|2[0-4]\d|[01]?\d{1,2})(\.(25[0-5]|2[0-4]\d|[01]?\d{1,2})){3})?)|((:[0-9A-Fa-f]{1,4}){1,2})))|(([0-9A-Fa-f]{1,4}:){4}(:[0-9A-Fa-f]{1,4}){0,1}((:((25[0-5]|2[0-4]\d|[01]?\d{1,2})(\.(25[0-5]|2[0-4]\d|[01]?\d{1,2})){3})?)|((:[0-9A-Fa-f]{1,4}){1,2})))|(([0-9A-Fa-f]{1,4}:){3}(:[0-9A-Fa-f]{1,4}){0,2}((:((25[0-5]|2[0-4]\d|[01]?\d{1,2})(\.(25[0-5]|2[0-4]\d|[01]?\d{1,2})){3})?)|((:[0-9A-Fa-f]{1,4}){1,2})))|(([0-9A-Fa-f]{1,4}:){2}(:[0-9A-Fa-f]{1,4}){0,3}((:((25[0-5]|2[0-4]\d|[01]?\d{1,2})(\.(25[0-5]|2[0-4]\d|[01]?\d{1,2})){3})?)|((:[0-9A-Fa-f]{1,4}){1,2})))|(([0-9A-Fa-f]{1,4}:)(:[0-9A-Fa-f]{1,4}){0,4}((:((25[0-5]|2[0-4]\d|[01]?\d{1,2})(\.(25[0-5]|2[0-4]\d|[01]?\d{1,2})){3})?)|((:[0-9A-Fa-f]{1,4}){1,2})))|(:(:[0-9A-Fa-f]{1,4}){0,5}((:((25[0-5]|2[0-4]\d|[01]?\d{1,2})(\.(25[0-5]|2[0-4]\d|[01]?\d{1,2})){3})?)|((:[0-9A-Fa-f]{1,4}){1,2})))|(((25[0-5]|2[0-4]\d|[01]?\d{1,2})(\.(25[0-5]|2[0-4]\d|[01]?\d{1,2})){3})))(%.+)?$/Du', $ipv6) )
{
print 'Nieprawidłowy adres IPv6/IPv4';
}
Rozwiązanie oparte o filter_var (PHP >= 5.2):
$ipv6 = trim('fe80::204:61ff:fe9d:f156');
if ( (bool)filter_var($ipv6, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) === false )
{
print 'Nieprawidłowy adres IPv6';
}
8. Wykrywanie kolorów RGB w postaci szesnastkowej
Wzorzec:
/^#?[0-9a-f]{3}(?:[0-9a-f]{3})?$/Diu
Opis:
Sprawdzić, czy wprowadzone dane są szesnastkowymi odpowiednikami zapisu kolorów modelu RGB.
Strona testowa:
Tutaj.
Tekst spełniający warunki:
#ff0000
Tekst nie spełniający warunków:
#a0hfg1 (g i h nie są znakami używanymi przy zapisie heksadecymalnym)
Rozwiązanie oparte o wyrażenie regularne:
$hex = trim('#0F15a2');
if ( !preg_match('/^#?[0-9a-f]{3}(?:[0-9a-f]{3})?$/Diu', $hex) )
{
print 'Nieprawidłowy kod szesnastkowy koloru!';
}
9. Proste sprawdzenie nazwy użytkownika
Wzorzec:
/^([a-z0-9]{1})([a-z0-9_-]{2,11})$/Diu
Opis:
Wprowadzone dane muszą rozpoczynać się od znaku alfanumerycznego. Kolejne znaki mogą być ponadto myślnikiem lub podkreśleniem. Długość tekstu nie może być większa niż 12ście znaków.
Strona testowa:
Brak.
Tekst spełniający warunki:
m1chu
Tekst nie spełniający warunków:
_nick (pierwszy znak nie jest cyfrą, ani literą)
Rozwiązanie oparte o wyrażenie regularne:
$username = trim('m1chu');
if ( !preg_match('/^([a-z0-9]{1})([a-z0-9_-]{2,11})$/Diu', $username) )
{
print 'Nieprawidłowa nazwa użytkownika!';
}
10. Proste sprawdzenie hasła użytkownika
Wzorzec:
/^(?=[a-z0-9_#@%\*-]*?[A-Z])(?=[a-z0-9_#@%\*-]*?[a-z])(?=[a-z0-9_#@%\*-]*?[0-9])([a-z0-9_#@%\*-]{8,24})$/Diu
Opis:
Wpisane hasło użytkownika musi mieć od ośmiu, do dwudziestu czterech znaków, pośród których musi być co najmniej jedna wielka litera, jedna mała i jedna cyfra. Dodatkowo dozwolone są: _, #, @, %, * i -.
Strona testowa:
Brak.
Tekst spełniający warunki:
1xY#n6%2V
Tekst nie spełniający warunków:
@1bbd2 (za krótki ciąg, brak wielkiej litery)
Rozwiązanie oparte o wyrażenie regularne:
$password = trim('To#jEst@_haSL-o%usera*');
if ( !preg_match('/^(?=[a-z0-9_#@%\*-]*?[A-Z])(?=[a-z0-9_#@%\*-]*?[a-z])(?=[a-z0-9_#@%\*-]*?[0-9])([a-z0-9_#@%\*-]{8,24})$/Diu', $password) )
{
print 'Nieprawidłowa nazwa użytkownika!';
}
11. Zaznaczanie frazy w tekście
Wzorzec:
/\b(fraza)\b/iu
Opis:
Zamienianie podanej frazy na inną lub wystylowanie jej formy. Przydatna funkcja w wyszukiwarkach.
Strona testowa:
Brak.
Działanie:
szukana_fraza -> szukana_fraza
Rozwiązanie oparte o wyrażenie regularne:
$text = 'Wyszukane frazy: wyrażenia, regularne, preg_match, preg_replace';
$find = 'regularne';
print preg_replace('/\b(' . $find . ')\b/iu', '<strong>\\1</strong>', $text);
$text = 'Wyszukane frazy: wyrażenia, regularne, preg_match, preg_replace';
$find = 'regularne';
print str_ireplace($find, '<strong>' . $find . '</strong>', $text);
12. Zamiana tekstowych emotikon na graficzne
Opis:
Podmiana tekstowych uśmieszków na ich odpowiedniki graficzne. Wersja z użyciem str_ireplace.
Strona testowa:
Brak.
Rozwiązanie oparte o wbudowaną funkcję PHP:
$text_format = array(
array(';)', ';-)', 'x)', ';]', ';-]'),
array(':)', ':-)', '=)', ':]', ':-]'),
array(':(', ':-(', '=(', ':[', ':-['),
array(';(', ';-(', 'x(', ';[', ';-['),
array(':P', ':-P', '=P'),
array(':D', ':-D', '=D'),
array(':*', ':-*', '=*'),
array(':O', ':-O', '=O'),
array(':/', ':-/', '=/')
);
$image_format = array(
'wink.png',
'smile.png',
'sad.png',
'cry.png',
'tongue.png',
'bigsmile.png',
'kiss.png',
'surprise.png',
'grimace.png'
);
$text = 'To jest przykładowy tekst ;] Prawda, że fajny? :-D Pogrymasiłbym trochę =/, ale po co? :) Także do zobaczenia :*';
foreach ( $text_format as $key => $val )
{
$text = str_ireplace($val, '<img src="smiles/' . $image_format[$key] . '" alt="' . $image_format[$key] . '" />', $text);
}
print $text;
13. Zamiana BBCode na HTML
Wzorzec przykładowy:
/\[b\](.*?)\[\/b\]/Dius
Opis:
Podmiana BBCode poprzez kod HTML. Funkcjonalność znana z forów internetowych.
Strona testowa:
Brak.
Działanie:
[i]pochylenie[/i] -> pochylenie
Uwagi:
W komercyjnych projektach należy skorzystać z bardziej zaawansowanych klas do obsługi tego problemu. Pozwoli to uniknąć np. problemu z nieprawidłowym zagnieżdżeniem kilku tagów BBCode w sobie.
Rozwiązanie oparte o wyrażenie regularne:
function bbcode2html($code) {
$search = array(
'/\[b\](.*?)\[\/b\]/Dius',
'/\[i\](.*?)\[\/i\]/Dius',
'/\[u\](.*?)\[\/u\]/Dius',
'/\[s\](.*?)\[\/s\]/Dius',
'/\[img\=(.*?)\](.*?)\[\/img\]/Dius',
'/\[img\](.*?)\[\/img\]/Dius',
'/\[url\](.*?)\[\/url\]/Dius',
'/\[url\=(.*?)\](.*?)\[\/url\]/Dius',
'/\[color\=(#?([a-f0-9]{6}|[a-f0-9]{3}))\](.*?)\[\/color\]/Dius',
'/\[size\=([1-9]{1}[0-9]{0,2})(px|pt|em)\](.*?)\[\/size\]/Dius',
'/\[font\=([a-z0-9\s"]+)\](.*?)\[\/font\]/Dius',
);
$replace = array(
'<strong>\\1</strong>',
'<em>\\1</em>',
'<span style="text-decoration: underline;">\\1</u>',
'<strike>\\1</strike>',
'<img src="\\2" alt="\\1" />',
'<img src="\\1" alt="" />',
'<a href="\\1">\\1</a>',
'<a href="\\1">\\2</a>',
'<span style="color: \\1;">\\2</span>',
'<span style="font-size: \\1\\2;">\\3</span>',
'<span style="font-family: \\1;">\\2</span>'
);
return preg_replace($search, $replace, $code);
}
14. Sprawdzenie poprawności wprowadzonego kodu pocztowego
Wzorzec:
/^[0-9]{2}-?[0-9]{3}$/Du
Opis:
Testowanie poprawności wpisanego kodu pocztowego (w formacie używanym w Polsce). Dozwolone są wersje z myślnikiem pomiędzy drugą i trzecią cyfrą, oraz bez niego.
Strona testowa:
Brak.
Tekst spełniający warunki:
62-150
Tekst nie spełniający warunków:
611-10
Rozwiązanie oparte o wyrażenie regularne:
$postcode = '61-610';
if ( !preg_match('/^[0-9]{2}-?[0-9]{3}$/Du', $postcode) )
{
print 'Nieprawidłowy kod pocztowy';
}
15. Operowanie na znacznikach XML/XHTML
Wzorzec:
/<([a-z]+)([\s]{1}[^=]+[=]{1}[^<]+)*(?:>(.*)<\/\1>|\s+\/>)/u
Opis:
Sprawdzenie znaczników XML/XHTML oraz pobranie treści znajdującej się pomiędzy nimi.
Strona testowa:
Brak.
Rozwiązanie oparte o wyrażenie regularne:
$tag = '<a href="http://m1chu.eu/" title="m1chu.eu - another devblog">m1chu.eu</a> - <strong>another devblog</strong>';
if ( !preg_match_all('/<([a-z]+)([\s]{1}[^=]+[=]{1}[^<]+)*(?:>(.*)<\/\1>|\s+\/>)/u', $tag, $matches, PREG_PATTERN_ORDER) )
{
print 'Nieprawidłowa konstrukcja znacznika';
}
else {
print_r($matches); // print_r($matches[3]) - lista treści zawieranych w tagach
}
Słowem zakończenia
Starałem się jak najdokładniej sprawdzić powyższe wzorce. Nie mniej jednak, jak to zwykle bywa, mogą się w nich znaleźć błędy. Jeżeli ktoś takowe znajdzie, ma jakieś pytania, czy lepsze propozycje to proszę o komentarze pod wpisem.
Jak wspomniałem na wstępie, uruchomiłem serwis pozwalający na sprawdzanie wyrażeń regularnych względem podanego tekstu. Jest on aktualnie w fazie testów, więc mogą występować błędy w jego działaniu. Po zakończeniu wprowadzania poprawek baza wpisów zostanie wyczyszczona do zera. Można go testować, a w przyszłości korzystać pod dwoma adresami:
- regexp.pl (adres główny)
- regexp.m1chu.eu (adres alternatywny)
Pod względem danych sesyjnych obydwa adresy działają niezależnie. Zapraszam do testowania i wyrażania swojego zdania na moim blogu, w komentarzach tego artykułu.
Zapraszam do zapoznania się także z powiązanymi artykułami:
Wpis ten został opublikowany dnia:
wtorek, 13 Październik 2009 o godzinie 22:23
w działach CSS, PHP, Webhosting, Świat IT.
Możesz śledzić rozwój tematu, w tym odpowiedzi dla tego artykułu poprzez kanał informacyjny RSS 2.0.
Możesz także zostawić swój komentarz lub trackbackować ze swojej własnej strony.
Nie wiem czemu podałeś przykłady dla preg_match, a nie wyłącznie filter_var.
Rozumiem, nie każdy musi mieć PHP 5.2, ale przykładów opartych o regexp jest tysiące w Sieci i nie potrzebnie powielasz i uczysz „nowych” staroci ;)
Można powiedzieć, że przykładów dla filter_var też jest już wiele. Po za tym, do filter_var wystarczy zbiór filtrów i flag, żeby bez problemu tę funkcję obsłużyć. A to można znaleźć w manualu (btw tips tego typu będzie na WH). Po za tym, filter_var nie zawsze się sprawdza (w przypadku FILTER_VALIDATE_URL zwraca niekiedy złe wyniki, co z resztą można zauważyć na stronach testowych podanych przeze mnie powyżej).
Co do tych wyrażeń, to nie wiem wg której specyfikacji masz te sprawdzanie adresu e-mail, ale na pewno przydało by się też weryfikacja przez MX, oraz w komentarzach do weryfikacji e-mail poprzez filter_var w manualu jeden z użytkowników napisał:
Więc wg mnie to nie jest poprawna walidacja adresu e-mail.
Pozdrawiam.
Wg jakich zasad cojack masz wylistowane w pierwszym punkcie. Nie starałem się spełnić wszystkich warunków żadnej specyfikacji. Kwestia długości i rozmiarów została także poruszona w ww. liście. Nie są one sprawdzane. Oczywiście nic nie stoi na przeszkodzie, żeby w jakimś hiper-uber-serwisie ktoś sobie zupgradeował ten przykładowy wzorzec, jeżeli widzi taką potrzebę, bo np. dziennie wchodzi mu na niego pół miliona osób via IPv6 ;]
Co do rekordów MX. Można przecież użyć checkdnsrr(), czy getmxrr() wraz z fsockopen() (itd.) w tym celu. Ale to już nie jest stricte kwestia tylko wyrażeń regularnych, więc jej nie poruszałem.
Nie mnie jednak, dzięki za komentarz :]
[...] 00:26 14/10/2009 15 przydatnych wyrażeń regularnych w PHP | m1chu.eu – another devblog m1chu.eu/…5-przydatnych-wyrazen-reg… Pokaż reakcje /* */ inne strony z tej witryny + obserwuj co [...]
Musze przyznac, ze te regulki sa malo dokladne. Na mojej stronie mozna znalesc link do wyrazenia regularnego ktory sprawdza maila zgodnie z ustalonymi normami… a nie na odwal sie. Dodatkowo te rzutowanie na bool’a jest zbedne. Polecam http://code.google.com/p/isemail/source/browse/trunk/is_email.php
Te regułki, czyli które dokładnie? Proszę, wymień je. Chętnie przeczytam także przykłady, dla których nie spełniają one swojego przeznaczenia.
Nie widzę też, gdzie na Twojej stronie można znaleźć link do tego wyrażenia regularnego sprawdzającego dokładniej (wg norm) adres e-mail. Jedyne co udało mi się wyszukać to przykład który podałeś z
filter_var, który zgoła jest tym samym, co ja dałem jako alternatywa do punktu o wzorcu sprawdzającym poprawność adresu e-mail. I jeżeli uważasz, że wyrażenie które podałem jest „na odwal” to, którego punktu z tych które wymieniłem w opisie nie spełnia? (bo kwestię „norm” już wyjaśniłem, wystarczy przeczytać ze zrozumieniem)PS: w swoim tipsie podałeś link do artykułu, w którym autor do weryfikacji używa znacznie uboższego wyrażenia, niż ja tutaj. Rozumiem, że pomimo tego, jego wzorzec nie jest „na odwal” (skoro go polecasz)?
http://code.google.com/p/isemail/source/browse/trunk/is_email.php
Grunt to znajomosc RFC 5322 :-)
http://ex-parrot.com/~pdw/Mail-RFC822-Address.html
Pozdro & Pocwicz
Problem z filter_var jest taki że ta funkcja sprawdza poprawność mail`a z RFC, ale niech ktoś spróbuje założyć takiego mail`a ‘marek…___@wp.pl’ na WP, no raczej nie przejdzie choć jest zgodny z RFC i filter_var go puści. Pytanie co chcemy sprawdzać, a najczęściej jest to jednak prawdopodobieństwo istnienie adresu a nie zgodność z RFC. Lepiej jednak sobie stworzyć własne wyrażenie regularne to nie jest żaden wielki problem. Druga sprawa to sprawdzenie czy adres istnieje, ale to nie ma nic wspólnego z walidacją, czyli sprawdzania rekordów MX i DNS`ów.
Witam
Pilnie prosze Cie o kontakt mailowy w sprawie strony http://regexp.m1chu.eu/.
Z gory dzieki za odzew.
Pozdrawiam
W wyrażeniu 6, w ostatnim przykładzie (Rozwiązanie oparte o filter_var (PHP >= 5.2)), jest niewielki błąd:
$email = trim('192.168.0.1');if ( (bool)filter_var($ipv4, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) === false )
{
print 'Nieprawidłowy adres IPv4';
}
Dzięki bardzo za wskazanie błędu. Poprawiłem :]
Ale na twojej stronce nie ma nifty corners:)
http://www.html.it/articoli/nifty/index.html