Apakah ada cara cepat untuk menemukan setiap kecocokan ekspresi reguler di Ruby? Saya telah melihat melalui objek Regex di STL Ruby dan mencari di Google tidak berhasil.
Tapi apa yang berbatasan dengan kasus ini? "cocokkan saya!". scan (/.../) = ["mat", "ch" "me!" ], tetapi semua kejadian dari / .../ akan menjadi ["mat", "atc", "tch", "ch", ...]
Michael Dickens
13
Bukan itu tidak akan. /.../ adalah regexp serakah yang normal. Itu tidak akan mundur pada konten yang cocok. Anda bisa mencoba menggunakan regexp yang malas tetapi bahkan itu mungkin tidak cukup. lihat regexp doc ruby-doc.org/core-1.9.3/Regexp.html untuk mengekspresikan regexp Anda dengan benar :)
Jean
49
ini tampak seperti WTF Ruby ... mengapa ini di String bukannya Regexp dengan hal-hal regexp lainnya? Bahkan tidak disebutkan di mana pun di dokumen untuk Regexp
Anentropic
9
Saya kira itu karena itu didefinisikan dan dipanggil pada String bukan pada Regex ... Tapi itu sebenarnya masuk akal. Anda dapat menulis ekspresi reguler untuk menangkap semua pertandingan menggunakan Regex # cocok dan beralih ke grup yang ditangkap. Di sini Anda menulis fungsi kecocokan parsial dan ingin itu diterapkan beberapa kali pada string yang diberikan, ini bukan tanggung jawab Regexp. Saya sarankan Anda memeriksa implementasi pemindaian untuk pemahaman yang lebih baik: ruby-doc.org/core-1.9.3/String.html#method-i-scan
Jean
9
@MichaelDickens: Dalam hal ini, Anda dapat menggunakan /(?=(...))/.
Konrad Borowski
67
Untuk menemukan semua string yang cocok, gunakan scanmetode String .
Mungkin Anda salah paham. Ekspresi reguler dari contoh pengguna yang saya jawab adalah: /(\d+)[m-t]/tidak /\d+[m-t]/Untuk menulis: re = /(\d+)[m-t]/; str.scan(re)sama str.scan(/(\d+)[mt]/)tetapi saya mendapatkan #> [["" 54 "], [" 1 "], [" 3 "]]dan tidak "54m", "1t", "3r"]Pertanyaannya adalah: jika saya memiliki ekspresi reguler dengan grup dan ingin menangkap semua pola tanpa mengubah yang biasa ekspresi (meninggalkan grup), bagaimana saya bisa melakukannya? Dalam hal ini, solusi yang mungkin, meskipun sedikit samar dan sulit dibaca, adalah:str.to_enum(:scan,re).map {$&}
MVP
-1
Anda bisa menggunakannya string.scan(your_regex).flatten. Jika regex Anda berisi grup, itu akan kembali dalam satu array polos.
Hapus pengelompokan dari your_regex = /(\d+)[m-t]/dan Anda tidak perlu menggunakan flatten. Contoh terakhir Anda menggunakan last_matchyang dalam hal ini mungkin aman, tetapi bersifat global dan mungkin bisa ditimpa jika ada regex yang cocok sebelum menelepon last_match. Sebaliknya mungkin lebih aman untuk digunakan string.match(regex).captures # => ["group_photo", "jpg"]atau string.scan(/\d+/) # => ["54", "3", "1", "7", "3", "0"]seperti yang ditunjukkan dalam jawaban lain, tergantung pada pola dan kebutuhan.
Jawaban:
Penggunaan
scan
harus melakukan trik:sumber
/(?=(...))/
.Untuk menemukan semua string yang cocok, gunakan
scan
metode String .Jika Anda ingin,,
MatchData
yang merupakan jenis objek yang dikembalikan olehmatch
metode Regexp , gunakan:Manfaat menggunakan
MatchData
adalah Anda dapat menggunakan metode sepertioffset
:Lihat pertanyaan ini jika Anda ingin tahu lebih banyak:
Membaca tentang variabel khusus
$&
,$'
,$1
,$2
di Ruby akan membantu juga.sumber
jika Anda memiliki regexp dengan grup:
Anda dapat menggunakan
scan
metode String untuk menemukan grup yang cocok:Untuk menemukan pola yang cocok:
sumber
str.scan(/\d+[m-t]/) # => ["54m", "1t", "3r"]
lebih idiomatis daripadastr.to_enum(:scan,re).map {$&}
/(\d+)[m-t]/
tidak/\d+[m-t]/
Untuk menulis:re = /(\d+)[m-t]/; str.scan(re)
samastr.scan(/(\d+)[mt]/)
tetapi saya mendapatkan #>[["" 54 "], [" 1 "], [" 3 "]]
dan tidak"54m", "1t", "3r"]
Pertanyaannya adalah: jika saya memiliki ekspresi reguler dengan grup dan ingin menangkap semua pola tanpa mengubah yang biasa ekspresi (meninggalkan grup), bagaimana saya bisa melakukannya? Dalam hal ini, solusi yang mungkin, meskipun sedikit samar dan sulit dibaca, adalah:str.to_enum(:scan,re).map {$&}
Anda bisa menggunakannya
string.scan(your_regex).flatten
. Jika regex Anda berisi grup, itu akan kembali dalam satu array polos.Regex dapat berupa grup yang diberi nama juga.
Anda juga dapat menggunakan
gsub
, itu hanya satu cara lagi jika Anda ingin MatchData.sumber
your_regex = /(\d+)[m-t]/
dan Anda tidak perlu menggunakanflatten
. Contoh terakhir Anda menggunakanlast_match
yang dalam hal ini mungkin aman, tetapi bersifat global dan mungkin bisa ditimpa jika ada regex yang cocok sebelum meneleponlast_match
. Sebaliknya mungkin lebih aman untuk digunakanstring.match(regex).captures # => ["group_photo", "jpg"]
ataustring.scan(/\d+/) # => ["54", "3", "1", "7", "3", "0"]
seperti yang ditunjukkan dalam jawaban lain, tergantung pada pola dan kebutuhan.