2012-09-17 13 views
12

To jest przykład ciąg:Jak ustawić część dopasowania do wyrażenia regularnego jako opcję opcjonalną?

123456#p654321 

Obecnie używam ten mecz, aby uchwycić 123456 i 654321 w dwóch różnych grup:

([0-9].*)#p([0-9].*) 

Ale okazjach #p654321 częścią łańcucha nie będzie tam, więc będę chciał uchwycić tylko pierwszą grupę. Próbowałem uczynić drugą grupę "opcjonalną", dodając do niej ?, która działa, ale tylko pod warunkiem, że na końcu pozostałego ciągu znajduje się #p.

Jaki byłby najlepszy sposób rozwiązania tego problemu?

Odpowiedz

33

Masz #p poza grupą przechwytywania, co powoduje, że jest to wymagana część wyniku. Niedozwolone jest również używanie znaku kropki (.). Kropka (w większości wariantów reg-ex) będzie pasować do dowolnej postaci. Zmień go na adres:

([0-9]*)(?:#p([0-9]*))? 

Składnia (?:) sposób można dostać się do grupy non-przechwytywanie. Następnie przechwytujemy tylko cyfry, którymi jesteś zainteresowany. Ostatecznie, robimy wszystko opcjonalnie.

Ponadto, większość wariantów reg-ex ma klasę znaków \d dla cyfr. Więc można uprościć jeszcze bardziej:

(\d*)(?:#p(\d*))? 

Jako kolejna osoba wskazała, operator * potencjalnie może dopasować zerowy cyfr. Aby temu zapobiec, należy użyć operatora + zamiast:

(\d+)(?:#p(\d+))? 
+0

Próbowałem tego wcześniej, i to działa jednak, jeśli istnieje druga część napisu następnie pierwsza grupa jest cały ciąg, i nic nie jest w druga grupa. – user1447941

+0

Kropka w reg-ex powoduje problem. Zobacz moją wersję. –

+0

A teraz druga grupa to '# p654321'. Widać, że jest to część dopasowania grupowego. – user1447941

4

Twój regex będą faktycznie pasuje nie cyfr, ponieważ użyłeś * zamiast +.
To co (chyba) chcesz:

(\d+)(?:#p(\d+))? 
+0

Masz rację; '+' byłby lepszym operatorem do użycia. Zastanowiłem się nad wprowadzeniem tej zmiany, ale PO nie określiła, czy możliwe są scenariusze bez cyfry. W związku z tym starałem się trzymać go jak najbliżej oryginału. –

Powiązane problemy