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
Daniel Beardsley
źródło

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"
Presidenten
źródło
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)

"[email protected]"[/\+([^@]+)/, 1] # matches capture group 1, i.e. what is inside ()
# => "account2"
"[email protected]"[/\+([^@]+)/]    # matches capture group 0, i.e. the whole match
# => "+account2"
Benjamin Crouzier
źródło
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
Slartibartfast
źródło
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 ).

Felix
źródło
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.

Lakmus
źródło