Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Regex i polskie znaki

1,458 views
Skip to first unread message

Witold Szczerba

unread,
Jul 28, 2009, 10:28:06 AM7/28/09
to
Hej,
tak się składa, że musiałem dzisiaj skorzystać z klas pakietu
java.util.regex i natrafiłem na coś dziwnego. Może od początku: chcę
zrobić porządek w tabeli z telefonami. Podczas importu, numer telefonu
ma zostać pozbawiony wszystkiego, co nie jest cyfrą:
(zmienne p1 i p2 wymyśliłem dla uproszczenia zapisu)

private static final Pattern nonDigitPattern = Pattern.compile("\\D");
[...]
String p1 = ......
String p2 = nonDigitPattern.matcher(p1).replaceAll("");
Tak więc jeśli
p1=" 61 12 34-567 pani Jadzia" to
p2="611234567"

Teraz chcę sprawdzić, czy w p1 nie ma przypadkiem czegoś, co jest
literą, jeśli coś takiego jest - to całe p1 wstawiam jeszcze do
komentarza, bo nie wiadomo co tam ważnego ktoś w starym systemie
zapisał; przykładowo jeśli był tak:
"61 12-23-456 wew. 28"
to w nowym będzie:

telefon: 61122345628
komentarz: 61 12-23-456 wew. 28

Użytkownik jak to zobaczy to sobie poprawi:
telefon: 61 122 345 628
komentarz: wew.28
i wszystko będzie git.

Zrobiłem to tak (i działa)
private static final Pattern letterPattern = Pattern.compile("[\\w&&[\
\D]]");
[...]
if (letterPattern.matcher(p1).find()) {
description = p1;
}

Podczas sprawdzania kodu znalazłem jednak mały niuans, oto wyniki
testów:
p1="1234a567"
letterPattern.matcher(p1).find() ==> true (ok)

ale:
p1="1234ą567" (polskie a)
letterPattern.matcher(p1).find() ==> false (a to co?)

Wg Pattern JavaDoc - "\w" oznacza: A word character. Klasyfikują się
do niego także cyfry, dlatego szukam po części wspólnej ze zbiorem
"non digit". Tylko dlaczego polskie litery alfabetu są odrzucane?

Jeśli zamiast tego dam [A-Ża-ż] to takie "ą" już znajdzie, ale co z
innymi znakami w innych językach? Myślałem, że takie "\w" załatwia
sprawę, teraz ciekawy jestem w ilu miejscach mogą się sypać aplikacje
tylko dlatego, że dostały się znaki spoza US-ASCII w tryby wyrażeń
regularnych w Javie :/

Michal Kleczek

unread,
Jul 28, 2009, 10:53:32 AM7/28/09
to
Witold Szczerba wrote:

[ciach]


> Zrobiłem to tak (i działa)
> private static final Pattern letterPattern = Pattern.compile("[\\w&&[\
> \D]]");

A moze:
"[\\p{L}]"

No i oczywiscie RTFM :) :
http://java.sun.com/javase/6/docs/api/java/util/regex/Pattern.html#ubc

Michal

--
Michal

Witold Szczerba

unread,
Jul 29, 2009, 3:26:38 AM7/29/09
to
On 28 Lip, 16:53, Michal Kleczek <klek...@gmail.com> wrote:
> > Zrobiłem to tak (i działa)
> > private static final Pattern letterPattern = Pattern.compile("[\\w&&[\
> > \D]]");
>
> A moze:
> "[\\p{L}]"

Dzięki za zwrócenie uwagi.
Mam jeszcze jedną zagadkę, nie wiem jak to zapisać: chodzi o złapanie
i wyrzucenie wszystkich nie-cyfr z wyjątkiem znaku "+" ale tylko,
jeśli jest on na początku, przykład:
xyz123+456abc ==> 123456
ale
+123+456abc ==> +123456

Próbowałem różnie, ale nic mi z tego nie wychodzi :/

marwis1978

unread,
Jul 29, 2009, 9:48:16 AM7/29/09
to

No chyba dużo prościej napisać oto taki programik:

public static void main(String[] args) {
String text = "+xyz123+456abc";
String result = "";
for (int i = 0; i < text.length(); i++) {
char znak = text.charAt(i);
if ((i == 0) && (znak == '+')) {
result += Character.toString(znak);
} else if (Character.isDigit(znak)) {
result += Character.toString(znak);
} else {
continue;
}
}
System.out.println(result);
}

Witold Szczerba

unread,
Jul 29, 2009, 10:41:17 AM7/29/09
to

No właśnie... albo się zna wyrażenia regularne i można robić takie
rzeczy za pomocą kilku znaków, albo trzeba pisać programy jak wyżej :/
Co do samego programu, to ja bym wynikowego String'a wyprodukował na
samym końcu, zamiast tworzyć i wyrzucać na śmietnik co chwilę nowy
obiekt (StringBuilder albo po prostu char[text.length]).

jolz

unread,
Jul 29, 2009, 11:51:06 AM7/29/09
to
>>> pattern = '^[^+0-9]|(?<=^.+)[^0-9]'
>>> String('xyz123+456abc').replaceAll(pattern, '')
'123456'
>>> String('+123+456abc').replaceAll(pattern, '')
'+123456'

Witold Szczerba

unread,
Jul 29, 2009, 1:33:12 PM7/29/09
to
On 29 Lip, 17:51, jolz <BardzoTajneKo...@interia.pl> wrote:
>  >>> pattern = '^[^+0-9]|(?<=^.+)[^0-9]'

Ożesz :/ Nic z tego nie rozumiem, heh...
Mógłbyś opisać jak dochodzi się do takiego czegoś?
Dla mnie to wygląda tak, że wyrażenie jest podzielone na dwie części:
a) ^[^+0-9]
b) (?<=^.+)[^0-9]
połączone operatorem 'lub', czyli:
a) pierwszy znak to nie (+ lub cyfra)
albo
b) dowolny ciąg nie cyfr, poprzedzony.... hmmm nie rozumiem...

konstrukcja:
(?<=X) oznacza: X, via zero-width positive lookbehind
ale X = ^.+ czyli:
dowolny znak (.)
dowloną ilość razy (+)
ale co tam robi ten (^) ?

jolz

unread,
Jul 29, 2009, 2:55:36 PM7/29/09
to
> b) dowolny ciąg nie cyfr, poprzedzony.... hmmm nie rozumiem...

(?<=^.+) jest po to zeby dopasowywac dowolny znak poza pierwszym

>
> konstrukcja:
> (?<=X) oznacza: X, via zero-width positive lookbehind
> ale X = ^.+ czyli:
> dowolny znak (.)
> dowloną ilość razy (+)

X+ X, one or more times

> ale co tam robi ten (^) ?

^ The beginning of a line

Ale rzeczywiscie ^ jest niepotrzebne. (?<=^.+)X sugeruje ze co najmniej
jeden znak jest na poczatku a (?<=.+)X oznacza ze co najmniej jeden znak
jest bezposrednio przed X i rezultat bedzie taki sam.


Witold Szczerba

unread,
Jul 30, 2009, 8:42:18 AM7/30/09
to
On Jul 29, 8:55 pm, jolz <BardzoTajneKo...@interia.pl> wrote:
>
> (?<=^.+) jest po to zeby dopasowywac dowolny znak poza pierwszym
>
> Ale rzeczywiscie ^ jest niepotrzebne. (?<=^.+)X sugeruje ze co najmniej
> jeden znak jest na poczatku a (?<=.+)X oznacza ze co najmniej jeden znak
> jest bezposrednio przed X i rezultat bedzie taki sam.

Super, teraz rozumiem :) Wydaje mi się jednak, ze (?<=.+) można
jeszcze uprościć do samej kropki: (?<=.), czyli ze musi być
jakikolwiek jeden znak poprzedzający nie-cyfrę. Całe wyrażenie wygląda
teraz tak:
^[^+1-9]|(?<=.)[^0-9]

W pierwszym nawiasie wstawiłem 1-9 zamiast 0-9, bo jak ktoś wpisze na
początku zero, to też wycinam, numer telefonu nie może się przecież
zaczynać od zera.

Michal Kleczek

unread,
Jul 30, 2009, 9:02:46 AM7/30/09
to
Witold Szczerba wrote:

[ciach]


> Całe wyrażenie wygląda
> teraz tak:
> ^[^+1-9]|(?<=.)[^0-9]
>

Dlatego nie lubie regexpow - nie daja sie czytac 2 mies. pozniej.
Chyba jednak wole ten imperatywny programik kolegi marwisa.

--
Michal

Witold Szczerba

unread,
Jul 30, 2009, 9:43:54 AM7/30/09
to
On Jul 30, 3:02 pm, Michal Kleczek <klek...@gmail.com> wrote:

> Witold Szczerba wrote:
> > Całe wyrażenie wygląda
> > teraz tak:
> > ^[^+1-9]|(?<=.)[^0-9]
>
> Dlatego nie lubie regexpow - nie daja sie czytac 2 mies. pozniej.
> Chyba jednak wole ten imperatywny programik kolegi marwisa.

Wyrażeń regularnych można się nauczyć, trzeba tylko chcieć. Ich
znajomość ma sporo zalet. Oprócz oszczędzania sobie czasu w pisaniu
imperatywnych programów, można z nich korzystać w wielu wielu
aplikacjach podczas pracy nad dowolnym dokumentem czy plikiem
tekstowym. Przykładowo OpenOffice pozwala szukać/zmieniać na bazie
wyrażeń reg., edytory w IDE (u mnie NetBeans) pozwalają przeszukiwać
nie tylko otwarty dokument, ale wszystkie pliki we wszystkich
projektach na bazie wyrażeń, midnight commander pozwala w wielu
miejscach zaznaczyć opcję reg ex... w linii poleceń powłoki można
odwołać się do wyrażeń (grep czy nawet odpalić perl'a z przełącznikiem
-e).
Dla kogoś kto się zna, takie ^[^+1-0]|(?<=.)[^0-9] jest oczywiste nie
mniej niż kilka(naście) linijek for/if/switch/case...

Michal Kleczek

unread,
Jul 30, 2009, 10:03:31 AM7/30/09
to
Witold Szczerba wrote:

> On Jul 30, 3:02 pm, Michal Kleczek <klek...@gmail.com> wrote:
>> Witold Szczerba wrote:
>> > Całe wyrażenie wygląda
>> > teraz tak:
>> > ^[^+1-9]|(?<=.)[^0-9]
>>
>> Dlatego nie lubie regexpow - nie daja sie czytac 2 mies. pozniej.
>> Chyba jednak wole ten imperatywny programik kolegi marwisa.
>
> Wyrażeń regularnych można się nauczyć, trzeba tylko chcieć. Ich
> znajomość ma sporo zalet.

Ja nie powiedzialem, ze sa bezuzyteczne.

[ciach]


> Dla kogoś kto się zna, takie ^[^+1-0]|(?<=.)[^0-9] jest oczywiste nie
> mniej niż kilka(naście) linijek for/if/switch/case...

Taa... znaczy autora trzeba trzymac w robocie tak dlugo, jak sie utrzymuje
software.

--
Michal

morwo

unread,
Jul 31, 2009, 3:31:00 AM7/31/09
to
On 30 Lip, 15:43, Witold Szczerba <pljosh.m...@gmail.com> wrote:
> Dla kogoś kto się zna, takie ^[^+1-0]|(?<=.)[^0-9] jest oczywiste nie
> mniej niż kilka(naście) linijek for/if/switch/case...

Ale czy regex nie jest bardziej zasobożerny niż kilka linijek for/if/
switch/case? Nie jestem biegły w tym temacie, ale jeśli coś jest
możliwe do napisania bez regexa, to staram się go nie wykorzystywać.

Przemysław Kowalczyk

unread,
Jul 31, 2009, 4:18:36 PM7/31/09
to
On Thu, 30 Jul 2009 16:03:31 +0200, Michal Kleczek <kle...@gmail.com>
wrote:
>> Dla kogoďż˝ kto siďż˝ zna, takie ^[^+1-0]|(?<=.)[^0-9] jest oczywiste nie
>> mniej ni� kilka(na�cie) linijek for/if/switch/case...

>
> Taa... znaczy autora trzeba trzymac w robocie tak dlugo, jak sie
> utrzymuje
> software.

Nie demonizuj. Moj szef (nie-programista, chociaz wyksztalcenie
techniczne) nauczyl sie wyrazen regularnych w ciagu 2 dni, a po tygodniu
trzaskal takie, ze ja mialem problemy z ich zrozumieniem, chociaz zeby na
regexpach zjadlem. Wiec jak sie chce, albo potrzebuje, to mozna. A
znajomosc regexpow nie jest wsrod programistow taka rzadka, zeby trzymac
kogos tylko dlatego.

pzdr
szeryf

--
Przemys�aw ,,Szeryf'' Kowalczyk :: http://szeryf.wordpress.com/

Przemysław Kowalczyk

unread,
Jul 31, 2009, 4:19:21 PM7/31/09
to
On Fri, 31 Jul 2009 09:31:00 +0200, morwo <lukasz...@gmail.com> wrote:

>> Dla kogoďż˝ kto siďż˝ zna, takie ^[^+1-0]|(?<=.)[^0-9] jest oczywiste nie
>> mniej ni� kilka(na�cie) linijek for/if/switch/case...
>
> Ale czy regex nie jest bardziej zasobo�erny ni� kilka linijek for/if/
> switch/case? Nie jestem bieg�y w tym temacie, ale je�li co� jest
> mo�liwe do napisania bez regexa, to staram si� go nie wykorzystywa�.

Premature optimization is the root of all evil.

0 new messages