Wyrażenia regularne w klasie String

Po urlopie teoretycznie powinno być lepiej niż przed nim – okazuje się, że to twierdzenie to bzdura. Wybitnie nie chce mi się nic, a tutaj blog czeka. Jednakże jak to zawsze bywa najgorzej jest zacząć, potem zaś to już z górki. Dziś na tapetę weźmiemy to, co spędza niejednemu programiście sen z powiek – oczywiście mowa o wyrażeniach regularnych.

Nie będę oczywiście dawał kursu samych wyrażeń – całkiem fajny można znaleźć u Andrzeja Gajdy – sama składnia PCRE jest zasadniczo wspólna i z jej przeniesieniem nie powinno być większych problemów. Wyrażenia regularne w Javie są obsługiwane rzecz jasna obiektowo, jednakże w inny niż w PHP sposób. Służą do tego klasy java.util.regex.*, których jednakże opisywanie mija się z celem. Zapraszam do dokumentacji, a także do tutoriala firmy Sun, gdzie można sobie o nich konkretnie poczytać. Ja natomiast dziś pragnę zwrócić uwagę na kilka metod, które do obsługi wyrażeń regularnych oferuje nam stara dobra klasa String

Po co zasadniczo tak rozbita obsługa wyrażeń regularnych? Wiem, wiem, że w PHP mamy kochanie preg_match i problemy się rozwiązują. Jednakże dość często zachodzi konieczność sprawdzenia za pomocą wyrażeń regularnych prostej wartości tekstowej, np. adresu email czy numeru konta. Zatem by nie uruchamiać całej maszynerii regexów w Javie (przypominam – java.util.regex.*), w klasie String zaimplementowano kilka malutkich metod, które pozwalają poradzić sobie z tym problemem. Pierwszą z nich jest String.match(“wyrazenie”). Ograniczona funkcjonalność pozwala tylko i wyłącznie na dopasowanie całego łańcucha znaków jako wyrażenia regularnego. Wystarczy spojrzeć na ten poniższy kod:


public class TestRegular {
public static void main(String[] args){
String wzorzec = "\\d";
String lancuch = "5";
System.out.print(lancuch.matches(wzorzec));
}
}

Metoda matches zwraca zawsze wartość bool – jeśli podany łancuch jest zgodny z podanym wyrażeniem (podkreślam raz jeszcze – cały łańcuch!!!), wówczas otrzymujemy TRUE, w przeciwnym wypadku oczywiście FALSE. Nazwy zmiennych chyba dość jasno obrazuja co i jak. Istotną tylko rzeczą jest fakt, że znaki specjalne (w tym przypadku określenie zbioru cyfr – “\w”, musi zostać oznaczone dodatkowym shashem by zadziałało poprawnie).

Drugą metodą jest replaceAll, która jak można się domyśleć zamienia wszystkie pasujące do wzorca elementy ciągu na inne. Oto przykład:


public class TestRegular {
public static void main(String[] args){
String mojLancuch = "Chlebi5 to programista PHP, ale Chlebik chce programować w Javie.";
System.out.print(mojLancuch.replaceAll("Chlebi\\d","Michał"));
}
}

Jak widać w wejściowym ciągu znaków specjalnie dorzuciłem cyfrę zamiast ostatniej litery mojego nicka i w ten sposób tylko pierwszy wyraz w ciągu został zamieniony (drugi nie został w ogóle przez Javę zauważony). Natomiast gdybyśmy chcieli tylkoi wyłącznie zamienić pierwsze wystąpienie kawałka ciągu, który byłby zgodny ze wzorcem należy zastosować metodę replaceFirst. Oto kod:


public class TestRegular {
public static void main(String[] args){
String mojLancuch = "Chlebik to programista PHP, ale Chlebik chce programować w Javie.";
System.out.print(mojLancuch.replaceFirst("Chlebik","Michał"));
}
}

Efektem będzie “Michał to programista PHP, ale Chlebik chce programować w Javie”. Dość to proste i logiczne. Na sam koniec zostawiłem bardziej skomplikowany przykład. Otóż pewnie niejeden raz programista PHP ma okazję skorzystać w pięknej funkcji jaką jest explode. Ano i w Javie mamy też takie explode i to do tego separatorem jest wyrażenie regularne. Rzecz nieraz przydatna, ale przedstawiona metoda (o nazwie split), ma jeden haczyk. Otóż jeśli separator znajduje się na końcu lub początku dzielonego łańcucha, w zwracanej przez metodę tablicy znajdzie się jeszcze jeden element (tablica to oczywiście tablica obiektów String) o długości zero. Przedstawia to poniższy kod:


public class TestRegular {
public static void main(String[] args){
String mojLancuch = "Chlebi5 to programista PHP, ale Chlebi5 chce programować w Javie.";
String[] mojaTablica;
mojaTablica = mojLancuch.split("Chlebi\\d");
for (String t : mojaTablica) {
System.out.println("Element tablicy to: " + t);
}
}
}

W wyniku działania programu na wyjściu dostaniemy taki oto efekt:

Element tablicy to:
Element tablicy to: to programista PHP, ale
Element tablicy to: chce programować w Javie.

Należy o tym pamiętać i potencjalnie przyciąć tablicę z początku lub końca. Metoda ta może również otrzymać jeszcze jeden parametr, jakim jest liczba zwracanych elementów. I tutaj kolejna uwaga – ilość zwróconych elementów nie oznacza przycięcia łańcucha? Najlepiej wyjaśnić to na przykładzie:


mojaTablica = mojLancuch.split("Chlebi\\d",2);

Otrzymamy wówczas tylko dwa elementy w tablicy, z czego pierwszy będzie pusty, a drugi będzie zawierał ciąg “Element tablicy to: to programista PHP, ale “. I właśnie tak nie jest! Zwracana tablica będzie miała następującą postać:

Element tablicy to:
Element tablicy to: to programista PHP, ale Chlebi5 chce programować w Javie.

Jak zatem widać zwrócona tablica zawiera w sobie cały łańcuch wejściowy, jednakże przycięty do podanej jako parametr liczby elementów.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s