Kembalikan kecocokan pertama dari Ruby regex

97

Saya sedang mencari cara untuk melakukan pertandingan regex pada string di Ruby dan membuatnya mengalami hubungan pendek pada pertandingan pertama.

String yang saya proses panjang dan dari apa yang tampak seperti cara standar ( matchmetode) akan memproses semuanya, mengumpulkan setiap kecocokan, dan mengembalikan objek MatchData yang berisi semua kecocokan.

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

Jawaban:

134

Anda bisa mencoba variableName[/regular expression/]. Ini adalah contoh keluaran dari 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
sumber
Apakah ini tidak melakukan pertandingan dan mengembalikan hasil pertama di belakang layar?
Gishu
7
Setelah melakukan benchmarking dengan berbagai string panjang dan melihat source C, ternyata Regex.match melakukan short circuit dan hanya menemukan match pertama.
Daniel Beardsley
3
Rapi, tidak tahu tentang pintasan ini.
Pierre
Apakah ada beberapa dokumentasi tentang pintasan ini? Saya mencari tinggi dan rendah untuk apa yang saya pikir adalah tugas yang relatif sederhana dan hanya memecahkan masalah saya setelah menemukan ini. Terima kasih!
dmourati
5
@dmourati Anda dapat menemukan fitur ini didokumentasikan dalam String # [] . Terima kasih telah bertanya tentang dokumen, karena dalam membacanya saya menemukan captureargumen - yang memungkinkan Anda mengembalikan tangkapan alih-alih pertandingan penuh.
slothbear
68

Anda dapat menggunakan []: (yang seperti 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
sumber
4
jawaban lengkap terbaik
akostadinov
23

Jika hanya keberadaan jodoh yang penting, Anda bisa pergi bersamanya

/regexp/ =~ "string"

Bagaimanapun, matchseharusnya hanya mengembalikan klik pertama, saat scanmenelusuri seluruh string. Karena itu jika

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

Saya belum yakin apakah fitur ini keren atau benar-benar gila, tetapi regex Anda dapat menentukan variabel lokal.

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

(Diambil dari http://ruby-doc.org/core-2.1.1/Regexp.html ).

Felix
sumber
Fitur luar biasa! Hanya yang saya butuhkan
RaphaMex
Peringatan: ini hanya berfungsi jika regex =~ string", not when string = ~ regex`
Christopher Oezbek
2

Ekspresi Reguler (regex) tidak lain adalah mesin keadaan terbatas (FSM).

FSM mencoba menjawab pertanyaan "Apakah keadaan ini mungkin atau tidak?"

Itu terus mencoba untuk membuat pola yang cocok sampai kecocokan ditemukan (sukses), atau sampai semua jalur dieksplorasi dan tidak ada kecocokan yang ditemukan (gagal).

Tentang kesuksesan, pertanyaan "Apakah keadaan ini mungkin atau tidak?" telah dijawab dengan "ya". Karenanya, tidak diperlukan pencocokan lebih lanjut dan regex kembali.

Lihat ini dan ini untuk lebih lanjut tentang ini.

Lebih lanjut: berikut adalah contoh menarik untuk mendemonstrasikan cara kerja regex. Di sini, regex digunakan untuk mendeteksi apakah suatu bilangan yang diberikan adalah bilangan prima. Contoh ini ada di perl, tapi bisa juga ditulis dengan ruby.

Lakmus
sumber