Zwraca pierwsze dopasowanie wyrażenia regularnego Ruby


97

Szukam sposobu na wykonanie dopasowania wyrażenia regularnego na łańcuchu w Rubim i spowodowanie zwarcia w pierwszym dopasowaniu.

Ciąg, który przetwarzam, jest długi iz tego, jak wygląda, standardowy sposób ( matchmetoda) przetworzyłby całość, zebrałby każde dopasowanie i zwrócił obiekt MatchData zawierający wszystkie dopasowania.

match = string.match(/regex/)[0].to_s

Odpowiedzi:


134

Mógłbyś spróbować variableName[/regular expression/]. Oto przykładowe wyjście irb:

irb(main):003:0> names = "erik kalle johan anders erik kalle johan anders"
=> "erik kalle johan anders erik kalle johan anders"
irb(main):004:0> names[/kalle/]
=> "kalle"

Czy to nie jest dopasowanie i zwrócenie pierwszego wyniku za kulisami?
Gishu,

7
Po kilku testach porównawczych z ciągami o różnej długości i spojrzeniu na źródło C okazuje się, że Regex.match robi zwarcie i znajduje tylko pierwsze dopasowanie.
Daniel Beardsley

3
Schludnie, nie wiedziałem o tym skrócie.
Pierre

Czy jest jakaś dokumentacja dotycząca tego skrótu? Szukałem wysoko i nisko, co uważałem za stosunkowo proste zadanie i rozwiązałem problem dopiero po znalezieniu tego. Dzięki!
dmourati

5
@dmourati Możesz znaleźć tę funkcję udokumentowaną w ciągu # [] . Dziękuję za pytanie o dokument, ponieważ czytając go znalazłem captureargument - który pozwala zwrócić przechwycenie zamiast pełnego dopasowania.
lenistwo

68

Możesz użyć []: (czyli jak match)

"foo+account2@gmail.com"[/\+([^@]+)/, 1] # matches capture group 1, i.e. what is inside ()
# => "account2"
"foo+account2@gmail.com"[/\+([^@]+)/]    # matches capture group 0, i.e. the whole match
# => "+account2"

4
najlepsza pełna odpowiedź
akostadinov

23

Jeśli ważne jest tylko istnienie dopasowania, możesz iść

/regexp/ =~ "string"

Tak czy inaczej, matchpowinno zwracać tylko pierwsze trafienie, podczas gdy scanprzeszukuje cały ciąg. Dlatego jeśli

matchData = "string string".match(/string/)
matchData[0]    # => "string"
matchData[1]    # => nil - it's the first capture group not a second match

8

Nie jestem jeszcze pewien, czy ta funkcja jest niesamowita, czy po prostu całkowicie szalona, ​​ale twoje wyrażenie regularne może definiować zmienne lokalne.

/\$(?<dollars>\d+)\.(?<cents>\d+)/ =~ "$3.67" #=> 0
dollars #=> "3"

(Zaczerpnięte z http://ruby-doc.org/core-2.1.1/Regexp.html ).


Niesamowita funkcja! Właśnie tego potrzebowałem
RaphaMex

Uwaga: działa tylko wtedy, gdy regex =~ string", not when string = ~ regex`
Christopher Oezbek

2

Wyrażenie regularne (regex) to nic innego jak automat skończony (FSM).

FSM próbuje odpowiedzieć na pytanie "Czy ten stan jest możliwy, czy nie?"

Próbuje dopasować wzorzec do momentu znalezienia dopasowania (sukces) lub do czasu, gdy wszystkie ścieżki zostaną zbadane i nie zostanie znalezione żadne dopasowanie (niepowodzenie).

Po sukcesie pytanie „Czy ten stan jest możliwy, czy nie?” otrzymała odpowiedź „tak”. Dlatego dalsze dopasowywanie nie jest konieczne i wyrażenie regularne powraca.

Zobacz to i to, aby uzyskać więcej informacji na ten temat.

Dalej: oto interesujący przykład pokazujący, jak działa regex. Tutaj wyrażenie regularne służy do wykrywania, czy podana liczba jest liczbą pierwszą. Ten przykład jest w perlu, ale równie dobrze można go napisać w języku ruby.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.