Thực thi Regexp trong Ruby
Bài đăng này đã không được cập nhật trong 6 năm
Class Regexp
Trong ruby, regular expression (biểu thức chính quy) tất cả được đóng gói trong lớp Regexp. có 3 cách để kiểu tra nhanh chóng:
Regexp.new(/.*/).class # => Regexp
/.*/.class # => Regexp
%r{.*}.class # => Regexp
Vậy thì câu hỏi tiếp theo: làm thế nào để kiểm tra 1 regex có match với 1 string ?
Class MatchData
Lớp Regexp cung cấp 1 phương thức Regexp#match với đầu vào là 1 string muốn kiểm tra.
/I love Ruby/.match('I love Ruby') # => #< MatchData "I love Ruby">
Phương thức Regexp#match trả về một đối tượng MatchData cho biết đoạn regex vừa rồi có match với toán tử string hay ko. Còn nếu trả về nil thì regex sẽ không match với đoạn string
/I love Ruby so much/.match('I love Ruby') # => nil
MatchData gồm nhiều thông tin, ví dụ: kiểm tra số lần đoạn regex match với string: MathData#length trả về 1 mảng những kết quả thu được: MatchData#to_a trả về 1 regex ban đầu: MatchData#regexp Ngoài ra bạn có thể tìm hiểu thêm tài liệu này, có rất nhiều hành động của đối tượng MatchData https://ruby-doc.org/core-2.5.0/MatchData.html
Các biến ma thuật
Ruby cung cấp cho ta những biến ma thuật, tự động nhận những kết quả khi chúng ta sử dụng Regexp
/(I love) (Ruby)/.match("Yes, I love Ruby. We're cool.")
# $~ returns the latest instance of MatchData
$~ # => #<MatchData "I love Ruby" 1:"I love" 2:"Ruby">
$& # => "I love Ruby" (The matching portion of the String)
$` # => "Yes, " (Equivalent to MatchData#pre_match method)
$' # => ". We're cool." (Equivalent to MatchData#post_match method)
$1 # => "I love"
$2 # => "Ruby"
$3 # => nil
Toán tử =~
Ruby cung cấp thêm toán tử khá đặc biệt là =~
Toán tử này match 1 regexp với 1 string, kết quả trả về là vị trí đầu tiên xuất hiện chuỗi trong string ứng với đoạn regexp
/(devscoop)/ =~ "http://ruby.devscoop.fr" # => 12
"http://ruby.devscoop.fr" =~ /(devscoop)/ # => 12
Tương tự, tất cả các biến ma thuật đều được khởi tạo sau mỗi phép thực hiện toán tử.
Đặt tên biến bên trong regexp
nhìn vào ví dụ:
if /(?<newsletter>devscoop)/ =~ 'http://ruby.devscoop.fr'
p newsletter # => "devscoop"
end
ta thấy biến newsletter chính là 1 MatchData đã tự động được gán giá trị sau khi thực thi toán tử =~
Một số điều khác
Không nằm trong lớp Regexp nhưng các phương thức sau cũng nhận những đối số là 1 regex thay vì 1 string như thông thường.
- String#scan => https://ruby-doc.org/core-2.5.0/String.html#method-i-scan
- String#gsub => https://ruby-doc.org/core-2.5.0/String.html#method-i-gsub
- String#[] => https://ruby-doc.org/core-2.5.0/String.html#method-i-5B-5D
Tham khảo: https://medium.com/@farsi_mehdi/regexp-implementation-in-ruby-5112fc219f1
All rights reserved