2009-09-09 21 views
7

Więc muszę dostać godziny, minuty i sekundy z wpisami takie jak:Dopasowywanie godzin/minut/sekund w wyrażeniach regularnych - lepszy sposób?

  • 04:43:12
  • 9.43.12
  • 1:00
  • 01,04

Pierwsze dwa to godziny, minuty i sekundy. Obok jest minuty i sekundy. Ostatnie dwa to tylko sekundy.

I wymyśliłem tego regexp, który działa ..:

\A(?<hours>\d{1,2})(?::|\.)(?<minutes>\d{1,2})(?::|\.)(?<seconds>\d{1,2})\z|\A(?<minutes>\d{1,2})(?::|\.)(?<seconds>\d{1,2})\z|\A(?<seconds>\d{1,2})\z 

Ale to brzydkie, i chcę byłaby go w dół, aby nie mieć 3 różne wyrażenia (głównie tylko do nauki). Próbowałem tego:

\A(?:(?<hours>\d{1,2})(?::|\.){0,1})(?:(?<minutes>\d{1,2})(?::|\.){0,1})(?:(?<seconds>\d{1,2}){0,1})\z 

Ale to nie działa - minuty i sekundy czasami się psują. Mój mózg cierpi i nie mogę zrozumieć, co robię źle.

+1

NIE jest to język-agnostyk. Składnia wyrażeń regularnych jest różna dla różnych języków. –

Odpowiedz

10

Moja sugestia:

(?:(?:(?<hh>\d{1,2})[:.])?(?<mm>\d{1,2})[:.])?(?<ss>\d{1,2}) 

strukturze:

(?:      # group 1 (non-capturing) 
    (?:     # group 2 (non-capturing) 
    (?<hh>\d{1,2})  #  hours 
    [:.]    #  delimiter 
)?     # end group 2, make optional 
    (?<mm>\d{1,2})  # minutes 
    [:.]     # delimiter 
)?      # end group 1, make optional 
(?<ss>\d{1,2})   # seconds (required) 

Jeśli chcesz, możesz owinąć regex w ograniczniki - jak granice tekstu \b lub kotew strunowych (^ i $).

EDYCJA: Zastanawiając się nad tym, możesz ograniczyć to dalej do czasów przechwytywania, które mają sens. Używać

[0-5]?\d 

w miejsce

\d{1,2} 

do wychwytywania wartości pomiędzy 0 a 59, gdzie jedynie odpowiednich (i kilka sekund).

+0

Uwielbiam strukturalne przykłady w regexp ... – gnarf

+0

Awesome! Działa świetnie - i uwielbia również formatowanie. Gdyby tylko mój redaktor to popierał, łatwiej by było z nim pracować. – Kjensen

+0

Czy nie jest znakiem komentarza dla wyrażeń regularnych w trybie "ignore whitespace and allow comments" zamiast "//"? – Joey

2

Proponuję następujące wyrażenie.

^(((?<Hour>[0-9]{1,2})[.:])?(?<Minute>[0-9]{1,2})[.:])?(?<Second>[0-9]{2})$

Pozwoli pojedyncze godzin cyfrowych w połączeniu z pojedynczą cyfrowych minut, jak 3:7:21. Jeśli nie jest to pożądane, wymagana jest niewielka modyfikacja.

^(((?<Hour>[0-9]{1,2})[.:](?=[0-9]{2}))?(?<Minute>[0-9]{1,2})[.:])?(?<Second>[0-9]{2})$

Pozytywny uprzedzona twierdzenie (?=[0-9]{2}) w drugiej wypowiedzi rozwiązuje ten problem.

1

nie ma na to naprawdę dobrej drogi, ponieważ to naprawdę zależy od konkretnej sytuacji, co należy zrobić, gdy nie wszystkie trzy części są określone. Na przykład w wielu przypadkach wolałbym interpretować 3:30 jako 3 godziny i 30 minut zamiast 3 minut i 30 sekund. Nie może to boleć o bycie jednoznacznym na ten temat i ułatwiać wyprowadzanie z wyrażeń regularnych tego, co oznaczają te rodzaje danych wejściowych.

W związku z tym osobiście uważam, że pierwsze wyrażenie nie jest wcale takie brzydkie - może to być mniej "magiczne", ale jest znacznie czytelniejsze i łatwiejsze w utrzymaniu. Upewnij się, że Ty i inni możecie nadal czytać i zmieniać kod później!

Jeśli twój język go obsługuje, użyłbym przedłużonych wyrażeń regularnych (z obsługą białych znaków i komentarzy) i podzielono je na trzy linie (lub 6 lub 9, jeśli wstawisz komentarz do oddzielnej linii). To nie zmieni regexu, ale na pewno będzie mniej brzydkie.

+0

Ważne punkty. Powodem, dla którego chciałbym, aby było lepiej, jest przede wszystkim nauka. – Kjensen

5

Nie testowałem tego jeszcze, ale to powinno działać:

^(?:(?:(?<hours>\d\d?)[:\.])?(?<minutes>\d\d?)[:\.])?(?<seconds>\d\d?)$ 

Edit:
Teraz mam przetestowane i sprawdzone, że to działa.:)

+0

To działa, ale uchwyci 3: 7: 21 to, co może być lub nie być pokazane jako 3:07:21. A tak przy okazji, nie ma potrzeby ucieczki z kropki w grupach znaków. (Czy nie mam racji? Czy implementacja regex tego wymaga?) –

+0

Odwrotny ukośnik na kropce w klasie znaków jest niepotrzebny. Dopuszczenie 3: 7: 21 przez 3:07:21 jest prawdopodobnie przykładem "hojności w tym, co akceptujesz". –

+0

Mam tendencję do ucieczki od niektórych postaci, które nie wymagają bezwzględnego ucieczki. Nawet jeśli klasa Regex nie potrzebuje go zrozumieć, może. :) – Guffa

Powiązane problemy