Có cách nào nhanh chóng để tìm mọi kết quả của biểu thức chính quy trong Ruby không? Tôi đã xem qua đối tượng Regex trong Ruby STL và tìm kiếm trên Google nhưng không có kết quả.
Có cách nào nhanh chóng để tìm mọi kết quả của biểu thức chính quy trong Ruby không? Tôi đã xem qua đối tượng Regex trong Ruby STL và tìm kiếm trên Google nhưng không có kết quả.
Câu trả lời:
Sử dụng scan
nên thực hiện các mẹo:
string.scan(/regex/)
/(?=(...))/
.
Để tìm tất cả các chuỗi phù hợp, sử dụng scan
phương thức của String .
str = "A 54mpl3 string w1th 7 numb3rs scatter36 ar0und"
str.scan(/\d+/)
#=> ["54", "3", "1", "7", "3", "36", "0"]
Nếu bạn muốn, MatchData
đó là loại đối tượng được trả về bởi match
phương thức Regapi , hãy sử dụng:
str.to_enum(:scan, /\d+/).map { Regexp.last_match }
#=> [#<MatchData "54">, #<MatchData "3">, #<MatchData "1">, #<MatchData "7">, #<MatchData "3">, #<MatchData "36">, #<MatchData "0">]
Lợi ích của việc sử dụng MatchData
là bạn có thể sử dụng các phương pháp như 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]
Xem những câu hỏi này nếu bạn muốn biết thêm:
Đọc sách về biến đặc biệt $&
, $'
, $1
, $2
trong Ruby sẽ rất hữu ích quá.
nếu bạn có một biểu thức chính quy với các nhóm:
str="A 54mpl3 string w1th 7 numbers scatter3r ar0und"
re=/(\d+)[m-t]/
bạn có thể sử dụng scan
phương thức của String để tìm các nhóm khớp:
str.scan re
#> [["54"], ["1"], ["3"]]
Để tìm mẫu phù hợp:
str.to_enum(:scan,re).map {$&}
#> ["54m", "1t", "3r"]
str.scan(/\d+[m-t]/) # => ["54m", "1t", "3r"]
là thành ngữ hơnstr.to_enum(:scan,re).map {$&}
/(\d+)[m-t]/
không /\d+[m-t]/
viết: re = /(\d+)[m-t]/; str.scan(re)
giống nhau str.scan(/(\d+)[mt]/)
nhưng tôi nhận được #> [["" 54 "], [" 1 "], [" 3 "]]
và không "54m", "1t", "3r"]
Câu hỏi là: nếu tôi có biểu thức chính quy với một nhóm và muốn chụp tất cả các mẫu mà không thay đổi thông thường biểu hiện (rời nhóm), làm thế nào tôi có thể làm điều đó? Theo nghĩa này, một giải pháp khả thi, mặc dù hơi khó hiểu và khó đọc, là:str.to_enum(:scan,re).map {$&}
Bạn có thể sử dụng string.scan(your_regex).flatten
. Nếu regex của bạn chứa các nhóm, nó sẽ trả về trong một mảng đơn giản.
string = "A 54mpl3 string w1th 7 numbers scatter3r ar0und"
your_regex = /(\d+)[m-t]/
string.scan(your_regex).flatten
=> ["54", "1", "3"]
Regex có thể là một nhóm được đặt tên là tốt.
string = 'group_photo.jpg'
regex = /\A(?<name>.*)\.(?<ext>.*)\z/
string.scan(regex).flatten
Bạn cũng có thể sử dụng gsub
, đó chỉ là một cách nữa nếu bạn muốn MatchData.
str.gsub(/\d/).map{ Regexp.last_match }
your_regex = /(\d+)[m-t]/
và bạn sẽ không cần sử dụng flatten
. Ví dụ cuối cùng của bạn sử dụng last_match
trong trường hợp này có thể là an toàn, nhưng là toàn cầu và có thể được ghi đè nếu có bất kỳ biểu thức chính nào được khớp trước khi gọi last_match
. Thay vào đó, nó có thể an toàn hơn để sử dụng string.match(regex).captures # => ["group_photo", "jpg"]
hoặc string.scan(/\d+/) # => ["54", "3", "1", "7", "3", "0"]
như thể hiện trong các câu trả lời khác, tùy thuộc vào mẫu và nhu cầu.