Regex - kody pocztowe

0

Witam. Chce zapisać zweryfikować wzorzec kodów pocztowych. Użyłem regexa do weryfikacji ale nie wiem czy trochę nie przekombinowałem i być może da się prościej
Generalnie chodzi o to, że chce przyjąć wzorzec kodu pocztowego w formach np:

 4_-__ , _3-___ lub __-3__ , itd

Chodzi mi o wszystkie możliwe kombinacje. I Jeśli jest brak cyfry to ma być podłoga ( _ ).

 new Regex("(^(([0-9]{2})|([0-9]{1}[_]{1})|([_]{2})|([_]{1}[0-9]{1}))-(([0-9]{3})|([_]{1}[0-9]{2})|([_]{2}[0-9]{1})|([0-9]{1}[_]{1}[0-9]{1})|([0-9]{1}[_]{2})|([_]{1}[0-9]{1}[_]{1}))$)|(^(([0-9]{2})|([0-9]{1}[_]{1})|([_]{1}[0-9]{1}))-([_]{3}))");
3

[_]{1} to to samo co _
[_]{2} to __
[0-9]{1} to tyle co [0-9]

już po tych zamianach masz

new Regex("(^(([0-9]{2})|([0-9]_)|(__)|(_[0-9]))-(([0-9]{3})|(_[0-9]{2})|(__[0-9])|([0-9]_[0-9])|([0-9]__)|(_[0-9]_))$)|(^(([0-9]{2})|([0-9]_)|(_[0-9]))-(___))");

a nie mogą być wszystkie cyfry zamienione na _? Wtedy wyrażenie jest banalne

^[_0-9]{2}-[_0-9]{3}$

jeśli musi być cyfra to:

^([_0-9][0-9]|[0-9][_0-9])-([_0-9]{2}[0-9]|[_0-9][0-9][_0-9]|[0-9][_0-9]{2})$

4
^(4\d-\d\d\d|\d3-\d\d\d|\d\d-3\d\d}$
3

@obscurity: i @szydlak Wasze wyrażenia nie działaja dla przypadków testowych:
https://regex101.com/r/txU3DZ/5
https://regex101.com/r/60itWe/1
https://regex101.com/r/rJ3eoT/1

Jesli kod pocztowy ma formę: dd-ddd, to może by tak?:
https://regex101.com/r/rJ3eoT/2

5

ok już kumam - ma być minimum jedna cyfra obojętne po lewej czy po prawej stronie, w takim razie możesz użyć wyrażenia look-ahead

^(?=.*[0-9].*)([_0-9]{2}-[_0-9]{3})$

https://regex101.com/r/W451hm/1

0

@lion137:
^[_0-9]{2} - oznacza, że na początku mogą być: 2 cyfry lub dwie podłogi lub ich kombinacje?

1

Jak tak to może tak?:
https://regex101.com/r/rJ3eoT/3

2

A czemu to ma być regex? Użyj najprostszej formy, czyli ^([_0-9]{2})-([_0-9]{3})$, a resztę odwal split + if.

Jeśli to koniecznie ma być regex (co mi się wydaje bezsensowne), to proponuję zrobić look-ahead'a: https://regex101.com/r/uzqizP/2

PS: @obscurity: Ubiegłeś mnie, ale grupa jest niepotrzebna, i drugie .* jest niepotrzebne: ^(?=.*\d)[_0-9]{2}-[_0-9]{3}$

0

@TomRiddle: Regex może być i jak pokazałem bez look ahead sie obędzie, a i testowanie chyba szybsze niż, jak sugerujesz z ifem i splitem; tylko wydaje mi sie, że @szydlak nie wie czy ma być co najmniej jedna liczba czy nie.

0
lion137 napisał(a):

@TomRiddle: Regex może być i jak pokazałem bez look ahead sie obędzie, a i testowanie chyba szybsze niż, jak sugerujesz z ifem i splitem; tylko wydaje mi sie, że @szydlak nie wie czy ma być co najmniej jedna liczba czy nie.

Unit testy i tak nie powinny znać wewnętrznej implementacji. Z punktu widzenia testerskiego to może być nawet 1000x if/else, i unit test/tester nie powinien być tego w stanie odróżnić. Unit testy tak czy tak warto mieć.

0

@lion137: co najmniej jedna cyfra w całym wzorcu. Czyli np 1_-___ jest ok

Jeśli tak, to ja już się nie produkuję :), rozwiązanie @TomRiddle załatwia sprawę, testy do @szydlak Ciebie:
https://regex101.com/r/uzqizP/3

0

Bo robię cennik i jest inny w zależności od kodu pocztowego. Ale nie podaje konkretnego kodu tylko jakby wzór. Czyli np ustalam cene dla kodów pocztowych ze wzorcem: 4_-___. Więc będzie obowiązywał wszystkie kody pocztowe zaczynające się od 4. - szydlak 7 minut temu

Ponieważ taki cennik ma modyfikować (chyba 1) ) zwykły człowiek, a nie programista, użyłbym czegoś znanego (power) userom, np maski jak do listowania plików albo like w SQL
W kodzie "silnika" zrobić swoje

  1. chyba że są programiści lubiący klepać cenniki?
0
AnyKtokolwiek napisał(a):

Bo robię cennik i jest inny w zależności od kodu pocztowego. Ale nie podaje konkretnego kodu tylko jakby wzór. Czyli np ustalam cene dla kodów pocztowych ze wzorcem: 4_-___. Więc będzie obowiązywał wszystkie kody pocztowe zaczynające się od 4. - szydlak 7 minut temu

Ponieważ taki cennik ma modyfikować (chyba 1) ) zwykły człowiek, a nie programista, użyłbym czegoś znanego (power) userom, np maski jak do listowania plików albo like w SQL
W kodzie "silnika" zrobić swoje

  1. chyba że są programiści lubiący klepać cenniki?

Czyli tak na prawdę chcesz zrobić parser maski kodu pocztowego? To skoro tak, to moim zdaniem maska __-___ też powinna być poprawna składniowo. Dopiero w późniejszej części aplikacji móglbyś decydować czy chcesz pozwolić na maski które dopuszczają wszystkie/ustawiać ich restrykcyjność. I jesli tak, to regexp ^[_\d]{2}-[_\d]{3}$ wystarczy :)

0

Troche offtop, istnieje na rynku cos bardziej ludzkiego spełniajacego założenia regexa?

0

Nie, nie istnieje, w tym segmencie rynku regex rzondzi :-D

0
lion137 napisał(a):

Nie, nie istnieje, w tym segmencie rynku regex rzondzi :-D

no nie, zwykła pętelka po charach ;) I to nawet nie w lambdach napisana

(o kurcze, zaraz mnie zawieszą w prawach członka Pi ^H^H^H... 4p )

0
TomRiddle napisał(a):
AnyKtokolwiek napisał(a):

Bo robię cennik i jest inny w zależności od kodu pocztowego. Ale nie podaje konkretnego kodu tylko jakby wzór. Czyli np ustalam cene dla kodów pocztowych ze wzorcem: 4_-___. Więc będzie obowiązywał wszystkie kody pocztowe zaczynające się od 4. - szydlak 7 minut temu

Ponieważ taki cennik ma modyfikować (chyba 1) ) zwykły człowiek, a nie programista, użyłbym czegoś znanego (power) userom, np maski jak do listowania plików albo like w SQL
W kodzie "silnika" zrobić swoje

  1. chyba że są programiści lubiący klepać cenniki?

Czyli tak na prawdę chcesz zrobić parser maski kodu pocztowego? To skoro tak, to moim zdaniem maska __-___ też powinna być poprawna składniowo. Dopiero w późniejszej części aplikacji móglbyś decydować czy chcesz pozwolić na maski które dopuszczają wszystkie/ustawiać ich restrykcyjność. I jesli tak, to regexp ^[_\d]{2}-[_\d]{3}$ wystarczy :)

Tak na prawdę to robię cennik. O osoba wysyła z frontu np takie coś

3_-___

oraz wartość kwoty. Ten regex służy mi tylko do tego, że zweryfikować czy poprawne dane są wysyłane z frontu i zapisane w bazie. Żeby np nikt nie mógł wysłać 3a-___. Cennik będzie zrobiony raz i tyle. Następnie w systemie robie zamówienie z miejscem odbioru (miejsce odbioru zawiera pełne dane adresowe z kodem pocztowym) Gdy tworze to zamówienie to z cennika pobieram wartość w zależności do czego pasuje kod pocztowy.
Stwierdziłem, że lepiej regexem weryfikować ten dane niż pisać jakieś szpagaty z ifami i pętlami po charach. I jak się okazuje ten regex jest bardzo, krótki i załatwia sprawę.

1
Escanor16 napisał(a):

Troche offtop, istnieje na rynku cos bardziej ludzkiego spełniajacego założenia regexa?

Można próbować klepać własny parser, ale parsery nie są przenośnie między językami. Np Haskell ma bardzo prosty i przyjemny AttoParsec, w którym próbowałem coś napisać, ale czy to jest lepsze niż RegExp to nie wiem

1
KamilAdam napisał(a):
Escanor16 napisał(a):

Troche offtop, istnieje na rynku cos bardziej ludzkiego spełniajacego założenia regexa?

Można próbować klepać własny parser, ale parsery nie są przenośnie między językami. Np Haskell ma bardzo prosty i przyjemny AttoParsec, w którym próbowałem coś napisać, ale czy to jest lepsze niż RegExp to nie wiem

To co napisałes to też jest wyrażenie regularne. To co klepie autor postu to też jest wyrażenie regularne. 3_-___. Rządzą się tymi samymi prawami, mają takie same wady i zalety, i wszystkie dostają input jako bezmózgi string. Więc do stringów które mają strukture, jak np JSON, HTML, etc. oczywiście używanie bezmózgich stringów się NIE NADAJE.

To co ludzie najcześciej mają na myśli mówiąc "regexp" albo "wyrażenie regularne", mają na myśli "wyrażenia regularne compatybilne z PCRE" (albo Perl-Compatible Regular Expression); co nie zmienia faktu że nawet *-*-*, to jest wyrażenie regularne.

1

Ja się zawsze zastanawiam dlaczego nie ma jakiegoś popularnego odpowiednika regexa z lepszym API typu

text
.NumberOfLength(3)
.Or()
.NumberOfLength(2)
.Then("-")
.NumberOfLength(3)
.Then("-")
.StringOfLength(3).MadeOf("ABC123")
.Matches()?

123-456-ABC

0
WeiXiao napisał(a):

Ja się zawsze zastanawiam dlaczego nie ma jakiegoś popularnego odpowiednika regexa z lepszym API typu

text
.NumberOfLength(3)
.Or()
.NumberOfLength(2)
.Then("-")
.NumberOfLength(3)
.Then("-")
.StringOfLength(3).MadeOf("ABC123")
.Matches()?

123-456-ABC

Moim zdaniem dlatego, że każdy kto zabrałby się za pisanie czegoś takiego skumałby jak słaby to jest pomysł. Z tego mogłyby korzytać początkujące osoby do klejenia bardzo podstawowych regexpów.

Spróbuj takim API zaprezentować zagnieżdżone grupy, alteracje grup, look aheady, look behind'y, atomic groups, custom code'y, conditional grupy, back referencje, nazwane grupy, back referencje do nazwanych grup, inline modifiery, conditional modifiery, auto capture/disable auto capture, PCRE callbacki, version comparison, sub-routine'y, rekursywne wzorce, etc.

Regexpy nie są skomplikowane przez przypadek, ale przez design.

0
TomRiddle napisał(a):

Moim zdaniem dlatego, że każdy kto zabrałby się za pisanie czegoś takiego skumałby jak słaby to jest pomysł. Z tego mogłyby korzytać początkujące osoby do klejenia bardzo podstawowych regexpów.

No i spoko, i wtedy nieskomplikowane (ale długie) rzeczy byłyby nadal czytelne, a do wszystkiego bardziej skomplikowanego => parsing czy regex(chociaż ja bym unikał).

1

Spróbuj takim API zaprezentować zagnieżdżone grupy, alteracje grup, look aheady, look behind'y, atomic groups, custom code'y, conditional grupy, back referencje, nazwane grupy, back referencje do nazwanych grup, inline modifiery, conditional modifiery, auto capture/disable auto capture, PCRE callbacki, version comparison, sub-routine'y, rekursywne wzorce, etc.

  • alteracje grup - operator <|>
  • look aheady -funkcja lookAhead
  • conditional grupy - funkcja option

itd.
Ogólnie całe API jest już zaprojektowane. Potrzebny jest tylko śmiałek który przepisze to z Haskella do C# :D
Dla Scali się udało XD

1 użytkowników online, w tym zalogowanych: 0, gości: 1