2024.07.15

Khám phá vài điều về Boundaries và Anchors bạn đã biết chưa?

Khám phá ngay sức mạnh của Anchors và Boundaries!

Boundaries và Anchors

Chúng ta đã đề cập về các ký tự đặc biệt (Special Characters) trong bài viết trước, nhưng chưa đi vào chi tiết về chức năng và vai trò của chúng. Trong bài này, chúng ta sẽ tập trung vào một số ký tự đặc biệt quan trọng như ^, $, và \. Những ký tự này đóng vai trò quan trọng trong việc xác định các vị trí chính xác trong chuỗi mà chúng ta cần kiểm tra hoặc xử lý. Thường được biết đến dưới hai tên gọi chính là Boundaries (ranh giới) và Anchors (mỏ neo).

 

Boundaries (ranh giới) và Anchors (mỏ neo) là gì? Chúng làm được những gì? Cùng khám phá lợi ích của Anchors Và Boundaries trong Regex.

Anchors (Mỏ neo)

Anchors(mỏ neo) - regex

Khi nhắc đến Anchors trong Regex, là nhắc đến ^ (Caret) và $ (Dollar sign).

^ (Caret): Đặt ở đầu một biểu thức regex, ^ biểu thị rằng mẫu cần khớp phải xuất hiện ở đầu chuỗi. Ví dụ: biểu thức regex /^Hello/ sẽ khớp với chuỗi “Hello world”“Hello” xuất hiện ở đầu chuỗi. Nhưng không khớp với “I say: Hello”, vì “I say: Hello” không bắt đầu bằng “Hello”.

$ (Dollar sign): Đặt ở cuối một biểu thức regex, $ biểu thị rằng mẫu cần khớp phải xuất hiện ở cuối chuỗi (hoặc cuối 1 dòng). Ví dụ: Biểu thức regex /cat$/ sẽ khớp với chuỗi “the white cat”“cat” xuất hiện ở cuối chuỗi. Cũng như với ^ (Caret), “The cat eats fish” có kết quả không khớp.

Như hai phần mô tả trên thì điều này có nghĩa là với ^ (Caret) và $ (Dollar sign), nếu chúng được đặt ở vị trí khác mà không đúng với vị trí như trong mô tả thì mẫu sẽ không khớp với bắt kỳ chuỗi nào.

Sử dụng kết hợp cả hai.

Trường hợp 1: Biểu thức regex (sử dụng cả hai Anchors) /^\d{3,10}$/ khớp với các chuỗi có từ 3 đến 10 chữ số.

  • “123456” // khớp với chuỗi này.
  • “A34567” // không khớp vì bắt đầu bằng ký tự “A”.
  • “3333 6666” // không khớp vì có khoảng trắng ở giữa.
  • ” 445566″ // không khớp vì có khoảng trắng ở đầu.
  • “445566 “ // không khớp vì có khoảng trắng ở cuối.

Trường hợp 2: Biểu thức regex /^[a-z].{3,6}\d$/ khớp với các chuỗi có các đặc điểm sau:

  • Bắt đầu bằng một ký tự chữ cái thường từ a đến z (^[a-z]).
  • Sau đó là một chuỗi với bất kỳ ký tự nào (bao gồm cả ký tự đặc biệt), có chiều dài từ 3 đến 6 ký tự (.{3,6}).
  • Kết thúc bằng một chữ số (\d).

      Ví dụ:

  • “a12345 8” // khớp với chuỗi này.
  • “a    8” // khớp với chuỗi này.
  • “A    8” // chuỗi không khớp, vì bắt đầu với chữ cái viết hoa.
  • “hello, Mai” // chuỗi không khớp vì kết thúc chuỗi không phải là chữ số.

Một điều cần chú ý với Anchors, cùng xem ví dụ sau để hiểu thêm:

Vd1: Biểu thức regex /^abc$/ với các trường hợp:

Trường hợp 1: “abc abc abc”

Trường hợp 2: “abc abc
abc”

Trường hợp 3: “abc
abc
abc”

Cần chú ý mỗi khi abc nằm trên dòng mới (newline character, ký hiệu \n hoặc \r\n. Newline character được gọi là Non-Printable Characters (các ký tự không in được), những ký tự này không nhìn thấy được bằng mắt thường). Cẩn thận để tránh nhằm lẫn giữa xuống dòng do màn hình hiển thị nhỏ, với xuống dòng do newline character. Có nghĩa là trên 1 dòng chỉ có duy nhất abc mà không có bất kỳ kí tự nào khác thì abc sẽ khớp với mẫu(**).

Hãy thử vào link https://regex101.com/r/OjC1nF/1 để xem các kết quả của ví dụ trên.

Vậy là đã tìm hiểu về Anchors (mỏ neo), tiếp theo hãy cùng tìm hiểu về Boundaries (ranh giới) trong phần bên dưới.

Boundaries (ranh giới)

Trước khi tìm hiểu về Boundaries, hãy cùng nhau làm rõ khái niệm về “word” và “non-word”:

  • Word” trong regex được hiểu là những ký tự chữ cái (a-z, A-Z), chữ số (0-9), hoặc dấu gạch dưới (_). Biểu thị ngắn gọn với short class \w hay [a-zA-Z0-9_].
    • Non-word” bao gồm các ký tự không phải là chữ cái, số hoặc dấu gạch dưới, như dấu cách(space), dấu chấm, dấu phẩy, và những ký tự đặc biệt ( @ # $ % ^ & * ). Biểu thị ngắn gọn với short class \W hay [^\w].

    Trong Boundaries có hai khái niệm một là Word Boundary (ký hiệu \b), hai là Not-word-boundary (ký hiệu \B)

    Word Boundary (ký hiệu \b)

    Word Boundary ( \b )

    Với word-boundary sẽ khớp các vị trí với một bên là word và một bên là non-word. Cùng xem hai ví dụ bên dưới để hiểu rõ hơn.

    Ví dụ 1: với mẫu regex /\b/

    • “abc def” // khớp 4 vị trí (chú ý vào dấu | biểu thị cho vị trí so khớp), 1 trước a, 2 sau c, 3 trước d, cuối cùng là sau f (|abc| |def|).
    • “abcdef” // khớp (|abcdef|)
    • “$$$” // không có vị trí nào khớp
    • “$fff” // khớp ($|fff|)

    Ví dụ 2: với mẫu regex /\ba/

    • “aaa” // khớp với chữ a đầu tiên (aaa).
    • “ba” // không khớp vì trước “a” không phải là một non-word.
    • “a a” // khớp, kết quả tìm thấy 2 chữ a (a a).
    • “ban an” // khớp với a trong “an” (ban an).
    • “trai na” //  không khớp.

    Ví dụ 3: với mẫu regex /\b@/

    • “aa@aa#@#” // kết quả ký tự “@” đầu tiên sẽ phù hợp (aa@aa#@#).

    Not-word-boundary (ký hiệu \B)

    Ngược lại với \b (word boundary). \B (Not-word-boundary) sẽ khớp các vị trí thỏa 1 trong 2 điều kiện sau:

    • Cả 2 bên đều là word:
      • “abc” // khớp thì vị trí khớp của nó sẽ là trước và sau b (a|b|c).
      • “Abcd” // kết quả vị trí khớp sẽ là trước b, trước c và trước d (A|b|c|d).
    • Cả 2 bên đều là non-word:
      • “%” kết quả sẽ là trước và sau % (|%|).
      • “a%%a” vị trí khớp sẽ nằm giữa hai % (a%|%a).
    • Not-word-boundary \B

    Điểm khác nhau giữa Boundaries và Anchors

    • Anchors: Chỉ được sử dụng ở vị trí đầu hoặc cuối của chuỗi trên một dòng, xác định vị trí tuyệt đối trong chuỗi.
    • Boundaries: Có thể ở bất kỳ vị trí nào trong chuỗi mà thỏa điều kiện của Boundaries (ranh giới) bên trên.

    Một vài chủ ý nhỏ:

    Khi dùng ^ (Caret), nếu dấu ^ được đặt trong cặp dấu ngoặc vuông [^a-z] thì nó sẽ có nghĩa là phủ định lại những giá trị đứng sau nó. Ví dụ, [^a-z] có nghĩa là sẽ bỏ qua hết các ký tự thường từ a đến z.

    Để xem kết quả của những ví dụ bên trên hãy copy các mẫu và chuỗi trong các ví dụ (khi copy các mẫu bạn nên bỏ dấu / ở đầu và cuối, đối với chuỗi thì bỏ qua ), truy cập vào đường link https://regex101.com/ để xem kết quả(**). Cuối cùng, hy vọng bài viết này giúp bạn hiểu rõ hơn về sự khác nhau giữa Boundaries và Anchors trong regex và cách sử dụng chúng hiệu quả.

    (**): Lưu ý rằng kết quả có thể khác biệt đôi chút, phụ thuộc vào REGEX FLAGS mà bạn chọn (trong bài viết này mình chọn regex flags là gm)

    Nguồn tham khảo: 

    https://www.regular-expressions.info/anchors.html

    https://www.rexegg.com/regex-anchors.php

     

      Subscribe
      Notify of
      0 Comments
      Inline Feedbacks
      View all comments