12/08/2018, 17:14

Thực thi Regexp trong Ruby

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 ...

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 ?

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

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

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ử.

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ử =~

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

0