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.
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.
Jawaban:
Penggunaan scan
harus melakukan trik:
string.scan(/regex/)
/(?=(...))/
.
Untuk menemukan semua string yang cocok, gunakan scan
metode String .
str = "A 54mpl3 string w1th 7 numb3rs scatter36 ar0und"
str.scan(/\d+/)
#=> ["54", "3", "1", "7", "3", "36", "0"]
Jika Anda ingin,, MatchData
yang merupakan jenis objek yang dikembalikan oleh match
metode Regexp , gunakan:
str.to_enum(:scan, /\d+/).map { Regexp.last_match }
#=> [#<MatchData "54">, #<MatchData "3">, #<MatchData "1">, #<MatchData "7">, #<MatchData "3">, #<MatchData "36">, #<MatchData "0">]
Manfaat menggunakan MatchData
adalah Anda dapat menggunakan metode seperti offset
:
match_datas = str.to_enum(:scan, /\d+/).map { Regexp.last_match }
match_datas[0].offset(0)
#=> [2, 4]
match_datas[1].offset(0)
#=> [7, 8]
Lihat pertanyaan ini jika Anda ingin tahu lebih banyak:
Membaca tentang variabel khusus $&
, $'
, $1
, $2
di Ruby akan membantu juga.
jika Anda memiliki regexp dengan grup:
str="A 54mpl3 string w1th 7 numbers scatter3r ar0und"
re=/(\d+)[m-t]/
Anda dapat menggunakan scan
metode String untuk menemukan grup yang cocok:
str.scan re
#> [["54"], ["1"], ["3"]]
Untuk menemukan pola yang cocok:
str.to_enum(:scan,re).map {$&}
#> ["54m", "1t", "3r"]
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)
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 {$&}
Anda bisa menggunakannya string.scan(your_regex).flatten
. Jika regex Anda berisi grup, itu akan kembali dalam satu array polos.
string = "A 54mpl3 string w1th 7 numbers scatter3r ar0und"
your_regex = /(\d+)[m-t]/
string.scan(your_regex).flatten
=> ["54", "1", "3"]
Regex dapat berupa grup yang diberi nama juga.
string = 'group_photo.jpg'
regex = /\A(?<name>.*)\.(?<ext>.*)\z/
string.scan(regex).flatten
Anda juga dapat menggunakan gsub
, itu hanya satu cara lagi jika Anda ingin MatchData.
str.gsub(/\d/).map{ Regexp.last_match }
your_regex = /(\d+)[m-t]/
dan Anda tidak perlu menggunakan flatten
. Contoh terakhir Anda menggunakan last_match
yang 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.