Regular Expressions trong JavaScript

Javascript căn bản | by Học Javascript

Trong lập trình, việc xử lý và thao tác với chuỗi là một phần quan trọng và thường xuyên gặp phải. JavaScript cung cấp nhiều phương thức làm việc với chuỗi, nhưng để tìm kiếm, kiểm tra hoặc thay thế nội dung một cách hiệu quả, Regular Expressions (RegEx) là một công cụ không thể thiếu. RegEx giúp lập trình viên xác định mẫu dữ liệu cụ thể trong chuỗi, từ việc kiểm tra định dạng email, số điện thoại cho đến trích xuất thông tin từ văn bản phức tạp.

Trong bài viết này, mình sẽ tìm hiểu chi tiết về cú pháp, cách sử dụng và các phương thức hỗ trợ Regular Expressions trong JavaScript, cùng với những ví dụ thực tế giúp bạn áp dụng RegEx một cách hiệu quả trong các dự án của mình.

Regular Expressions trong JavaScript là gì?

Regular Expressions (biểu thức chính quy, hay viết tắt là RegEx) là một công cụ mạnh mẽ để làm việc với chuỗi trong JavaScript. RegEx cho phép bạn tìm kiếm, so khớp và thao tác với các chuỗi bằng cách sử dụng mẫu ký tự (pattern) thay vì các phương pháp xử lý chuỗi thông thường.

Cú pháp của RegEx trong JavaScript thường được viết trong cặp dấu gạch chéo /pattern/ hoặc sử dụng RegExp constructor:

// Cách 1: Sử dụng dấu gạch chéo
const regex1 = /hello/;  

// Cách 2: Sử dụng hàm tạo RegExp
const regex2 = new RegExp("hello");

Cả hai cách trên đều tạo ra một biểu thức chính quy để tìm kiếm từ "hello" trong một chuỗi.

Công dụng của RegEx trong lập trình JavaScript

RegEx giúp lập trình viên xử lý chuỗi hiệu quả hơn nhờ khả năng tìm kiếm, kiểm tra và thay thế nội dung dựa trên mẫu ký tự. Một số công dụng chính của RegEx trong JavaScript bao gồm:

  • Tìm kiếm chuỗi trong văn bản:
    Giúp kiểm tra xem một từ hoặc cụm từ có tồn tại trong một chuỗi hay không.
  • Kiểm tra định dạng dữ liệu:
    Hữu ích trong việc xác thực email, số điện thoại, địa chỉ IP, mật khẩu, v.v.
  • Thay thế nội dung trong chuỗi:
    Có thể sử dụng RegEx để tìm và thay thế văn bản một cách linh hoạt.
  • Tách chuỗi thành mảng dựa trên mẫu ký tự:
    Thay vì chỉ tách bằng dấu phẩy hoặc khoảng trắng, bạn có thể dùng RegEx để chia chuỗi theo nhiều tiêu chí phức tạp.

Một số ứng dụng thực tế của RegEx

RegEx được ứng dụng rộng rãi trong lập trình, đặc biệt trong xử lý dữ liệu và xác thực đầu vào. Dưới đây là một số ví dụ thực tế:

Xác thực địa chỉ email

const emailRegex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;
console.log(emailRegex.test("[email protected]")); // true
console.log(emailRegex.test("invalid-email")); // false
Kiểm tra số điện thoại
const phoneRegex = /^\d{10}$/; 
console.log(phoneRegex.test("0987654321")); // true
console.log(phoneRegex.test("12345")); // false
Tìm kiếm từ trong văn bản
const text = "JavaScript is awesome!";
const regex = /javascript/i; // 'i' để không phân biệt chữ hoa, chữ thường
console.log(regex.test(text)); // true
Thay thế từ trong chuỗi
const sentence = "Hello world!";
const newSentence = sentence.replace(/world/, "JavaScript");
console.log(newSentence); // "Hello JavaScript!"
Tách chuỗi theo nhiều dấu phân cách
const str = "apple,banana;orange|grape";
const fruits = str.split(/[,;|]/);
console.log(fruits); // ["apple", "banana", "orange", "grape"]

Cách tạo biểu thức Chính quy trong JavaScript

Trong JavaScript, bạn có thể tạo biểu thức chính quy (Regular Expressions - RegEx) bằng hai cách:

  • Dùng dấu gạch chéo (/pattern/)
  • Dùng đối tượng RegExp (new RegExp("pattern", "flags"))

Cả hai cách đều có tác dụng giống nhau, nhưng mỗi cách có ưu và nhược điểm riêng.

Sử dụng cú pháp dấu gạch chéo (/pattern/)

Cách này là ngắn gọn và dễ hiểu nhất. Bạn chỉ cần đặt mẫu ký tự trong dấu / /, có thể thêm các flag (cờ) để điều chỉnh cách hoạt động của biểu thức.

Ví dụ:

const regex = /hello/;  // Tạo một biểu thức chính quy tìm kiếm từ "hello"
console.log(regex.test("hello world")); // true
console.log(regex.test("hi there")); // false

Các flag phổ biến trong RegEx

Flag Ý nghĩa
g (global) Tìm kiếm tất cả kết quả khớp trong chuỗi
i (ignore case) Không phân biệt chữ hoa, chữ thường
m (multiline) Xử lý nhiều dòng

Ví dụ với flag:

const regex = /hello/i;  // Không phân biệt hoa thường
console.log(regex.test("Hello world")); // true

Sử dụng đối tượng RegExp

Ngoài cách dùng dấu / /, bạn có thể dùng constructor RegExp() để tạo biểu thức chính quy.

Cú pháp:

const regex = new RegExp("pattern", "flags");

Ví dụ:

const regex1 = new RegExp("hello");  // Tương đương với /hello/
console.log(regex1.test("hello world")); // true

const regex2 = new RegExp("hello", "i"); // Không phân biệt hoa thường
console.log(regex2.test("HELLO world")); // true

So sánh hai cách tạo RegEx

Cách tạo Ưu điểm Nhược điểm
/pattern/ Dễ đọc, ngắn gọn Không thể tạo RegEx từ biến động
new RegExp("pattern") Cho phép tạo RegEx từ biến động Dài dòng hơn, khó đọc

Ví dụ khi cần tạo biểu thức chính quy từ một chuỗi động:

const userInput = "hello";
const regex = new RegExp(userInput, "i"); // Tạo RegEx từ biến động
console.log(regex.test("HELLO world")); // true

Các ký tự và cú pháp cơ bản Regular Expressions trong JavaScript

Regular Expressions (RegEx) có một số ký tự và cú pháp đặc biệt giúp xử lý chuỗi một cách mạnh mẽ và linh hoạt hơn. Dưới đây là các thành phần quan trọng cần biết.

Ký tự thông thường

Các ký tự thông thường bao gồm chữ cái, số và ký tự đặc biệt không có ý nghĩa đặc biệt trong RegEx. Khi bạn sử dụng chúng trong một biểu thức chính quy, chúng sẽ được tìm kiếm đúng như vậy trong chuỗi.

Ví dụ:

const regex = /hello/;  // Tìm kiếm chuỗi "hello"
console.log(regex.test("hello world")); // true
console.log(regex.test("hi there")); // false
  • hello trong RegEx chỉ khớp với chính xác chuỗi "hello" trong văn bản.

Ký tự đại diện (Meta Characters)

Các ký tự đại diện giúp tìm kiếm các nhóm ký tự một cách dễ dàng mà không cần liệt kê từng ký tự.

Ký tự Ý nghĩa
. Đại diện cho bất kỳ ký tự nào ngoại trừ xuống dòng (\n)
\d Bất kỳ chữ số nào (0-9)
\w Bất kỳ ký tự chữ cái (a-z, A-Z), số (0-9) hoặc dấu gạch dưới (_)
\s Khoảng trắng (space, tab, newline)

Ví dụ:

const regex1 = /h.llo/;  // Khớp với bất kỳ ký tự nào giữa "h" và "llo"
console.log(regex1.test("hello")); // true
console.log(regex1.test("hallo")); // true

const regex2 = /\d\d\d/; // Kiểm tra xem có đúng 3 chữ số liên tiếp không
console.log(regex2.test("123")); // true
console.log(regex2.test("12a")); // false

const regex3 = /\w\w\w/; // Ba ký tự bất kỳ (chữ cái, số, _)
console.log(regex3.test("abc")); // true
console.log(regex3.test("a_1")); // true
console.log(regex3.test("a!1")); // false (vì `!` không thuộc `\w`)

Ký tự đặc biệt (Escape Characters)

Một số ký tự có ý nghĩa đặc biệt trong RegEx (như . hoặc *). Để tìm kiếm chúng như một ký tự thông thường, bạn cần dùng dấu \ (escape character).

Ký tự Ý nghĩa
\. Dấu chấm thực sự (.)
\* Ký tự * thực sự
\+ Ký tự + thực sự
\? Ký tự ? thực sự
\( \) Dấu ngoặc đơn thực sự

Ví dụ:

const regex = /google\.com/;  // Tìm kiếm "google.com"
console.log(regex.test("google.com")); // true
console.log(regex.test("googleXcom")); // false (vì `.` bị thay bằng `X`)

Nhóm ký tự (Character Sets & Ranges)

Dùng [ ] để xác định một tập hợp các ký tự mà bạn muốn khớp.

Biểu thức Ý nghĩa
[abc] Khớp với một trong các ký tự a, b, hoặc c
[a-z] Khớp với bất kỳ ký tự nào từ a đến z
[0-9] Khớp với bất kỳ chữ số nào từ 0 đến 9
[a-zA-Z0-9_] Khớp với chữ cái, số và dấu _

Ví dụ:

const regex = /[aeiou]/; // Kiểm tra xem có nguyên âm nào không
console.log(regex.test("hello")); // true
console.log(regex.test("sky")); // false

Ký tự phủ định (Negated Character Sets)

Dùng [^ ] để phủ định một tập hợp ký tự.

Biểu thức Ý nghĩa
[^abc] Bất kỳ ký tự nào không phải a, b, hoặc c
[^0-9] Bất kỳ ký tự nào không phải số

Ví dụ:

const regex = /[^aeiou]/; // Tìm ký tự không phải nguyên âm
console.log(regex.test("hello")); // true (vì có "h", "l")
console.log(regex.test("aeiou")); // false

Biểu thức lặp (Quantifiers)

Dùng để xác định số lần lặp lại của một ký tự hoặc nhóm ký tự.

Biểu thức Ý nghĩa
a* 0 hoặc nhiều lần ("", "a", "aa", ...)
a+ 1 hoặc nhiều lần ("a", "aa", nhưng không phải "")
a? 0 hoặc 1 lần ("" hoặc "a")
a{n} Chính xác n lần ("aaa" nếu a{3})
a{n,} Ít nhất n lần
a{n,m} Từ n đến m lần

Ví dụ:

const regex = /a{2,4}/; // Tìm "a" xuất hiện từ 2 đến 4 lần
console.log(regex.test("aa"));   // true
console.log(regex.test("aaa"));  // true
console.log(regex.test("aaaa")); // true
console.log(regex.test("aaaaa"));// false

Nhóm và lựa chọn (Grouping & Alternation)

Ký tự Ý nghĩa
() Nhóm các ký tự
` `

Ví dụ:

const regex = /(cat|dog)/; // Tìm "cat" hoặc "dog"
console.log(regex.test("I have a dog")); // true
console.log(regex.test("I have a cat")); // true
console.log(regex.test("I have a bird")); // false

Biểu thức khớp vị trí (Anchors & Boundaries)

Ký tự Ý nghĩa
^ Khớp với đầu chuỗi
$ Khớp với cuối chuỗi
\b Khớp với ranh giới từ

Ví dụ:

const regex1 = /^hello/; // "hello" phải ở đầu chuỗi
console.log(regex1.test("hello world")); // true
console.log(regex1.test("say hello")); // false

const regex2 = /\bword\b/; // "word" phải là một từ riêng biệt
console.log(regex2.test("a word here")); // true
console.log(regex2.test("wordplay")); // false

Các phương thức làm việc với Regular Expressions trong JavaScript

JavaScript cung cấp nhiều phương thức để làm việc với Regular Expressions (RegEx), giúp kiểm tra, tìm kiếm, thay thế hoặc cắt chuỗi một cách linh hoạt. Dưới đây là các phương thức quan trọng bạn cần biết.

test() – Kiểm tra chuỗi có khớp không

Phương thức test() dùng để kiểm tra xem một chuỗi có khớp với biểu thức chính quy hay không.

  • Cú pháp:
regex.test(string)
  • Trả về: true nếu có khớp, false nếu không khớp.

Ví dụ:

const regex = /hello/;
console.log(regex.test("hello world")); // true
console.log(regex.test("hi there")); // false

Ứng dụng: Kiểm tra nhanh một chuỗi có chứa từ khóa hay không.

exec() – Trả về kết quả tìm thấy

Phương thức exec() sẽ tìm kiếm chuỗitrả về mảng kết quả đầu tiên tìm thấy. Nếu không có kết quả nào, nó trả về null.

Cú pháp:

regex.exec(string)

Trả về: Một mảng chứa thông tin kết quả, hoặc null nếu không tìm thấy.

Ví dụ:

const regex = /hello/;
const result = regex.exec("hello world");
console.log(result[0]);  // "hello"
console.log(result.index); // 0 (vị trí khớp đầu tiên)
console.log(result.input); // "hello world"

Ứng dụng: Lấy vị trí của từ trong chuỗi.

match() – Tìm kiếm trong chuỗi

Phương thức match() tìm tất cả kết quả khớp trong chuỗi.

Cú pháp:

string.match(regex)

Trả về:

  • Một mảng chứa tất cả kết quả nếu tìm thấy.
  • null nếu không có kết quả.

Ví dụ:

const text = "hello world, hello everyone";
const regex = /hello/g;
console.log(text.match(regex)); // ["hello", "hello"]

Ứng dụng: Lấy danh sách tất cả từ khớp trong một đoạn văn bản.

matchAll() – Tìm tất cả kết quả với thông tin chi tiết

Phương thức matchAll() trả về một iterator chứa tất cả kết quả khớp cùng với thông tin vị trí.

Cú pháp:

string.matchAll(regex)

Trả về: Một iterator chứa các mảng kết quả, có thể dùng for...of để duyệt.

Ví dụ:

const text = "hello world, hello everyone";
const regex = /hello/g;
const matches = text.matchAll(regex);

for (const match of matches) {
  console.log(match[0], "tại vị trí", match.index);
}
// Output:
// hello tại vị trí 0
// hello tại vị trí 13

Ứng dụng: Lấy vị trí từng từ trong văn bản.

replace() – Thay thế nội dung khớp

Phương thức replace() giúp thay thế chuỗi khớp đầu tiên hoặc toàn bộ chuỗi (nếu có flag g).

  • Cú pháp:
string.replace(regex, replacement)
  • Trả về: Chuỗi mới đã thay thế.

Ví dụ:

const text = "I love JavaScript";
const newText = text.replace(/JavaScript/, "Python");
console.log(newText); // "I love Python"

Ứng dụng: Thay thế nội dung trong chuỗi (chỉ thay đổi lần đầu tiên khớp).

replaceAll() – Thay thế tất cả nội dung khớp

Phương thức replaceAll() giúp thay thế tất cả nội dung khớp (không cần g flag).

Cú pháp:

string.replaceAll(regex, replacement)

Trả về: Chuỗi mới đã thay thế.

Ví dụ:

const text = "hello world, hello everyone";
const newText = text.replaceAll("hello", "hi");
console.log(newText); // "hi world, hi everyone"

Ứng dụng: Thay thế tất cả nội dung trong văn bản mà không cần g flag.

split() – Cắt chuỗi bằng biểu thức chính quy

Phương thức split() giúp tách một chuỗi dựa trên biểu thức chính quy.

  • Cú pháp:
string.split(regex)
  • Trả về: Một mảng các phần tử.

Ví dụ:

const text = "apple, banana, cherry";
const fruits = text.split(/,\s*/);
console.log(fruits); // ["apple", "banana", "cherry"]

ứng dụng: Chia tách dữ liệu từ chuỗi văn bản.

Phương thức Mô tả Trả về
test() Kiểm tra chuỗi có khớp không true hoặc false
exec() Trả về kết quả tìm thấy đầu tiên Mảng hoặc null
match() Trả về tất cả kết quả khớp Mảng hoặc null
matchAll() Trả về iterator chứa tất cả kết quả Iterator
replace() Thay thế nội dung khớp đầu tiên Chuỗi mới
replaceAll() Thay thế tất cả nội dung khớp Chuỗi mới
split() Cắt chuỗi theo biểu thức chính quy Mảng

Ứng dụng thực tế của Regular Expressions trong JavaScript

Regular Expressions (RegEx) là công cụ mạnh mẽ trong JavaScript để kiểm tra, tìm kiếm và xử lý chuỗi. Dưới đây là một số ứng dụng thực tế phổ biến của RegEx.

Kiểm tra định dạng email

Kiểm tra một chuỗi có đúng định dạng email hợp lệ không.

  • Email phải chứa ký tự @ và dấu . (dot).
  • Tên miền phải có ít nhất hai ký tự.

Ví dụ:

function validateEmail(email) {
    const regex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;
    return regex.test(email);
}

console.log(validateEmail("[email protected]")); // true
console.log(validateEmail("invalid-email@com")); // false
console.log(validateEmail("[email protected]")); // true

Ứng dụng: Kiểm tra email hợp lệ khi người dùng đăng ký hoặc đăng nhập.

Kiểm tra số điện thoại

Kiểm tra số điện thoại có đúng định dạng hay không.

  • Số điện thoại có thể bắt đầu bằng +84 (Việt Nam) hoặc số 0.
  • Chỉ chứa số và có 9-11 chữ số.
function validatePhoneNumber(phone) {
    const regex = /^(?:\+84|0)[0-9]{9,10}$/;
    return regex.test(phone);
}

console.log(validatePhoneNumber("+84901234567")); // true
console.log(validatePhoneNumber("0901234567")); // true
console.log(validatePhoneNumber("123456")); // false

Ứng dụng: Kiểm tra số điện thoại khi đăng ký tài khoản.

Kết bài

Regular Expressions (RegEx) là một công cụ mạnh mẽ trong JavaScript giúp xử lý chuỗi hiệu quả, từ kiểm tra đầu vào, tìm kiếm, thay thế, cho đến phân tích dữ liệu. Với khả năng áp dụng linh hoạt, RegEx hỗ trợ lập trình viên thực hiện các thao tác như kiểm tra email, số điện thoại, mật khẩu mạnh, chuẩn hóa văn bản, tách từ, và chuyển đổi định dạng ngày tháng một cách nhanh chóng và chính xác.

Tuy nhiên, do cú pháp RegEx khá phức tạp, người dùng cần thực hành thường xuyên để nắm vững các ký tự đặc biệt, biểu thức lặp, nhóm và phương thức làm việc với JavaScript. Khi sử dụng RegEx trong các dự án thực tế, cần kiểm tra kỹ lưỡng để đảm bảo tính chính xác và hiệu suất.

Hy vọng qua bài viết này, bạn đã có cái nhìn tổng quan về RegEx và có thể áp dụng vào các tình huống thực tế trong lập trình JavaScript.

Bài viết liên quan