2011-07-23 9 views
60

Wiem, że mogę napisać oświadczenie na temat Rubiego, aby sprawdzić mecz z wyrażeń regularnych. Chciałbym jednak użyć danych dopasowania w moim oświadczeniu o zwrocie. Coś jak ten pół-pseudokod:Jak napisać instrukcję przełącznika Ruby (case ... when) z regex i backreferences?

foo = "10/10/2011" 

case foo 
    when /^([0-9][0-9])/ 
     print "the month is #{match[1]}" 
    else 
     print "something else" 
end 

Jak mogę to osiągnąć?

Dzięki!


Tylko uwaga: Rozumiem, że nigdy nie użyłbym instrukcji switch dla prostego przypadku jak wyżej, ale to tylko jeden przykład. W rzeczywistości to, co próbuję osiągnąć, to dopasowywanie wielu potencjalnych wyrażeń regularnych do daty, która może być zapisana na różne sposoby, a następnie przetwarzanie jej klasą daty Rubiego.

+0

Ruby's Date.parse obsługuje wiele formatów daty. Próbowałeś tego? – raine

+0

Mimo że nie odpowiada na to pytanie, warto spojrzeć na klejnot Chronic ... – DGM

Odpowiedz

108

Odniesienia do najnowszej regex pasujące grupy są zawsze zapisywane w pseudo variables$1 do $9:

case foo 
when /^([0-9][0-9])/ 
    print "the month is #{$1}" 
else 
    print "something else" 
end 

Można również użyć zmiennej pseudo ten $LAST_MATCH_INFO dostać w całej MatchData obiektu. Może to być przydatne podczas używania nazwanych przechwytów:

case foo 
when /^(?<number>[0-9][0-9])/ 
    print "the month is #{$LAST_MATCH_INFO['number']}" 
else 
    print "something else" 
end 
+0

... po prostu dobrze zrobione i +1 :) – apneadiving

+0

Todah, Yossi - Bidiuk ma she hipasti. –

+0

@Yossi Czy masz jakieś źródło do swojego komentarza dotyczącego bezpieczeństwa wątków? Właśnie przeprowadziłem eksperyment w ruby ​​1.8.7, który wydaje się wskazywać, że jest bezpieczny dla wątków! (Wątek pasujący do wyrażenia regularnego co sekundę - sprawdzanie irb, jeśli lokalne dopasowania są blokowane) – Joel

4

Oto alternatywne podejście, które daje taki sam wynik, ale nie używa przełącznika. Jeśli umieścisz swoje wyrażeń regularnych w tablicy, można zrobić coś takiego:

res = [ /pat1/, /pat2/, ... ] 
m = nil 
res.find { |re| m = foo.match(re) } 
# Do what you will with `m` now. 

Deklarowanie m zewnątrz bloku pozwala mu nadal dostępne po find odbywa się z bloku i find zatrzyma jak tylko block zwraca prawdziwą wartość, dzięki czemu uzyskujesz takie samo zachowanie skrótów, jakie daje przełącznik. Daje to pełny MatchData, jeśli jest to potrzebne (być może chcesz użyć nazwanych grup przechwytywania w wyrażeniach regularnych) i ładnie oddziela wyrażenia regularne od logiki wyszukiwania (które mogą ale nie muszą dawać jaśniejszego kodu), możesz nawet załadować swoje wyrażenia regularne z plik konfiguracyjny lub wybierz, który zestaw chciałeś w czasie wykonywania.

+0

Myślałem również o bezpieczeństwie wątków za pomocą podejścia 'case'. Może chcesz użyć podejścia mu w scenariuszu z gwintem, zamiast zmiennej globalnej z podejściem przypadku (?) – Casper