มีวิธีที่รวดเร็วในการค้นหาการจับคู่ของนิพจน์ทั่วไปใน Ruby หรือไม่? ฉันได้ตรวจสอบวัตถุ Regex ใน Ruby STL และค้นหาใน Google โดยไม่มีประโยชน์
มีวิธีที่รวดเร็วในการค้นหาการจับคู่ของนิพจน์ทั่วไปใน Ruby หรือไม่? ฉันได้ตรวจสอบวัตถุ Regex ใน Ruby STL และค้นหาใน Google โดยไม่มีประโยชน์
คำตอบ:
การใช้scan
ควรทำเคล็ดลับ:
string.scan(/regex/)
/(?=(...))/
ในกรณีนี้คุณสามารถใช้
ในการค้นหาสตริงที่ตรงกันทั้งหมดให้ใช้scan
วิธีการของสตริง
str = "A 54mpl3 string w1th 7 numb3rs scatter36 ar0und"
str.scan(/\d+/)
#=> ["54", "3", "1", "7", "3", "36", "0"]
หากคุณต้องการMatchData
ซึ่งเป็นประเภทของวัตถุที่ส่งคืนโดยmatch
วิธีRegexp ให้ใช้:
str.to_enum(:scan, /\d+/).map { Regexp.last_match }
#=> [#<MatchData "54">, #<MatchData "3">, #<MatchData "1">, #<MatchData "7">, #<MatchData "3">, #<MatchData "36">, #<MatchData "0">]
ประโยชน์ของการใช้MatchData
คือคุณสามารถใช้วิธีการเช่น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]
ดูคำถามเหล่านี้หากคุณต้องการทราบข้อมูลเพิ่มเติม:
อ่านเกี่ยวกับตัวแปรพิเศษ$&
, $'
, $1
, $2
ทับทิมจะเป็นประโยชน์มากเกินไป
หากคุณมี regexp กับกลุ่ม:
str="A 54mpl3 string w1th 7 numbers scatter3r ar0und"
re=/(\d+)[m-t]/
คุณสามารถใช้scan
วิธีการของ String เพื่อค้นหากลุ่มที่ตรงกัน:
str.scan re
#> [["54"], ["1"], ["3"]]
วิธีค้นหารูปแบบการจับคู่:
str.to_enum(:scan,re).map {$&}
#> ["54m", "1t", "3r"]
str.scan(/\d+[m-t]/) # => ["54m", "1t", "3r"]
มีสำนวนมากกว่าstr.to_enum(:scan,re).map {$&}
/(\d+)[m-t]/
ไม่/\d+[m-t]/
เขียน: re = /(\d+)[m-t]/; str.scan(re)
เหมือนกันstr.scan(/(\d+)[mt]/)
แต่ฉันได้ #> [["" 54 "], [" 1 "], [" 3 "]]
ไม่ใช่"54m", "1t", "3r"]
คำถามคือถ้าฉันมีการแสดงออกปกติกับกลุ่มและต้องการจับรูปแบบทั้งหมดโดยไม่ต้องเปลี่ยนปกติ การแสดงออก (ออกจากกลุ่ม) ฉันจะทำอย่างไร ในแง่นี้คำตอบที่เป็นไปได้แม้ว่าจะเป็นความลับเล็ก ๆ น้อย ๆ และอ่านยากก็คือ:str.to_enum(:scan,re).map {$&}
string.scan(your_regex).flatten
คุณสามารถใช้ หาก regex ของคุณมีกลุ่มมันจะกลับมาในอาร์เรย์ธรรมดาเดียว
string = "A 54mpl3 string w1th 7 numbers scatter3r ar0und"
your_regex = /(\d+)[m-t]/
string.scan(your_regex).flatten
=> ["54", "1", "3"]
Regex สามารถเป็นกลุ่มที่มีชื่อเช่นกัน
string = 'group_photo.jpg'
regex = /\A(?<name>.*)\.(?<ext>.*)\z/
string.scan(regex).flatten
คุณสามารถใช้gsub
มันเป็นอีกวิธีหนึ่งถ้าคุณต้องการ MatchData
str.gsub(/\d/).map{ Regexp.last_match }
your_regex = /(\d+)[m-t]/
flatten
ใช้ตัวอย่างสุดท้ายของคุณlast_match
ซึ่งในกรณีนี้น่าจะเป็นความปลอดภัย แต่เป็นทั่วโลกและอาจจะถูกเขียนทับถ้า regex ใด ๆ last_match
ที่ถูกจับคู่ก่อนที่จะโทร แต่อาจจะปลอดภัยกว่าที่จะใช้string.match(regex).captures # => ["group_photo", "jpg"]
หรือstring.scan(/\d+/) # => ["54", "3", "1", "7", "3", "0"]
ดังที่แสดงในคำตอบอื่น ๆ ขึ้นอยู่กับรูปแบบและความต้องการ