RegExp
Baseline
Widely available
*
This feature is well established and works across many devices and browser versions. It’s been available across browsers since July 2015.
* Some parts of this feature may have varying levels of support.
Đối tượng RegExp được dùng để so khớp văn bản với một mẫu (pattern).
Để có phần giới thiệu về biểu thức chính quy, hãy đọc chương về biểu thức chính quy trong hướng dẫn JavaScript. Để biết thông tin chi tiết về cú pháp biểu thức chính quy, hãy đọc tài liệu tham khảo biểu thức chính quy.
Mô tả
>Ký hiệu literal và constructor
Có hai cách để tạo đối tượng RegExp: ký hiệu literal và constructor.
- Ký hiệu literal nhận một mẫu giữa hai dấu gạch chéo, theo sau là các flags tùy chọn, sau dấu gạch chéo thứ hai.
- Hàm constructor nhận một chuỗi hoặc đối tượng
RegExplàm tham số đầu tiên và một chuỗi flags tùy chọn làm tham số thứ hai.
Ba biểu thức sau tạo ra cùng một đối tượng biểu thức chính quy:
const re = /ab+c/i; // literal notation
// OR
const re = new RegExp("ab+c", "i"); // constructor with string pattern as first argument
// OR
const re = new RegExp(/ab+c/, "i"); // constructor with regular expression literal as first argument
Trước khi biểu thức chính quy có thể được sử dụng, chúng phải được biên dịch. Quá trình này cho phép chúng thực hiện so khớp hiệu quả hơn. Thông tin thêm về quá trình này có thể được tìm thấy trong dotnet docs.
Ký hiệu literal dẫn đến biên dịch biểu thức chính quy khi biểu thức được đánh giá. Mặt khác, constructor của đối tượng RegExp, new RegExp('ab+c'), dẫn đến biên dịch biểu thức chính quy tại runtime.
Sử dụng chuỗi làm đối số đầu tiên của constructor RegExp() khi bạn muốn xây dựng biểu thức chính quy từ đầu vào động.
Flags trong constructor
Biểu thức new RegExp(/ab+c/, flags) sẽ tạo một RegExp mới sử dụng source của tham số đầu tiên và các flags được cung cấp bởi tham số thứ hai.
Khi sử dụng hàm constructor, các quy tắc escape chuỗi thông thường (đặt \ trước các ký tự đặc biệt khi bao gồm trong chuỗi) là cần thiết.
Ví dụ, hai biểu thức sau tương đương:
const re = /\w+/;
// OR
const re = new RegExp("\\w+");
Xử lý đặc biệt cho regex
Note:
Liệu có gì đó là "regex" có thể được kiểm tra theo kiểu duck-typed. Nó không nhất thiết phải là RegExp!
Một số phương thức dựng sẵn sẽ xử lý regex theo cách đặc biệt. Chúng quyết định liệu x có phải là regex hay không thông qua nhiều bước:
xphải là một đối tượng (không phải kiểu nguyên thủy).- Nếu
x[Symbol.match]không phải làundefined, kiểm tra xem nó có truthy không. - Ngược lại, nếu
x[Symbol.match]làundefined, kiểm tra xemxcó được tạo bằng constructorRegExpkhông. (Bước này hiếm khi xảy ra, vì nếuxlà đối tượngRegExpkhông bị can thiệp, nó phải có thuộc tínhSymbol.match.)
Lưu ý rằng trong hầu hết các trường hợp, nó sẽ đi qua kiểm tra Symbol.match, có nghĩa là:
- Một đối tượng
RegExpthực sự có giá trị thuộc tínhSymbol.matchlà falsy nhưng không phảiundefined(kể cả khi mọi thứ khác còn nguyên vẹn, nhưexecvà[Symbol.replace]()) có thể được dùng như thể nó không phải là regex. - Một đối tượng không phải
RegExpcó thuộc tínhSymbol.matchsẽ được coi như thể nó là regex.
Sự lựa chọn này được thực hiện vì [Symbol.match]() là thuộc tính chỉ định nhất rằng một thứ gì đó được dùng để so khớp. (exec cũng có thể được dùng, nhưng vì nó không phải là thuộc tính symbol, sẽ có quá nhiều false positive.) Các nơi xử lý regex theo cách đặc biệt bao gồm:
String.prototype.endsWith(),startsWith(), vàincludes()némTypeErrornếu đối số đầu tiên là regex.String.prototype.matchAll()vàreplaceAll()kiểm tra xem flag global có được đặt không nếu đối số đầu tiên là regex trước khi gọi phương thức[Symbol.matchAll]()hoặc[Symbol.replace]()của nó.- Constructor
RegExp()trực tiếp trả về đối sốpatternchỉ khipatternlà regex (trong số một vài điều kiện khác). Nếupatternlà regex, nó cũng sẽ truy vấn các thuộc tínhsourcevàflagscủapatternthay vì ép kiểupatternthành chuỗi.
Ví dụ, String.prototype.endsWith() sẽ ép tất cả đầu vào thành chuỗi, nhưng sẽ ném lỗi nếu đối số là regex, vì nó chỉ được thiết kế để so khớp chuỗi, và việc sử dụng regex có thể là lỗi của developer.
"foobar".endsWith({ toString: () => "bar" }); // true
"foobar".endsWith(/bar/); // TypeError: First argument to String.prototype.endsWith must not be a regular expression
Bạn có thể vượt qua kiểm tra bằng cách đặt [Symbol.match] thành giá trị falsy không phải undefined. Điều này có nghĩa là regex không thể được dùng cho String.prototype.match() (vì không có [Symbol.match], match() sẽ tạo một đối tượng RegExp mới với hai dấu gạch chéo bao quanh được thêm bởi re.toString()), nhưng nó có thể được dùng cho hầu hết mọi thứ khác.
const re = /bar/g;
re[Symbol.match] = false;
"/bar/g".endsWith(re); // true
re.exec("bar"); // [ 'bar', index: 0, input: 'bar', groups: undefined ]
"bar & bar".replace(re, "foo"); // 'foo & foo'
Các thuộc tính RegExp kiểu Perl
Lưu ý rằng một số thuộc tính RegExp có cả tên dài và ngắn (kiểu Perl). Cả hai tên luôn tham chiếu đến cùng một giá trị. (Perl là ngôn ngữ lập trình mà JavaScript mô phỏng biểu thức chính quy.) Xem thêm các thuộc tính RegExp không dùng nữa.
Constructor
RegExp()-
Tạo một đối tượng
RegExpmới.
Thuộc tính tĩnh
RegExp.$1, …,RegExp.$9Deprecated-
Các thuộc tính tĩnh chỉ đọc chứa các kết quả so khớp chuỗi con trong ngoặc đơn.
RegExp.input($_) Deprecated-
Thuộc tính tĩnh chứa chuỗi cuối cùng mà biểu thức chính quy được so khớp thành công.
RegExp.lastMatch($&) Deprecated-
Thuộc tính tĩnh chỉ đọc chứa chuỗi con được so khớp cuối cùng.
RegExp.lastParen($+) Deprecated-
Thuộc tính tĩnh chỉ đọc chứa kết quả so khớp chuỗi con trong ngoặc đơn cuối cùng.
RegExp.leftContext($`) Deprecated-
Thuộc tính tĩnh chỉ đọc chứa chuỗi con đứng trước kết quả so khớp gần nhất.
RegExp.rightContext($') Deprecated-
Thuộc tính tĩnh chỉ đọc chứa chuỗi con đứng sau kết quả so khớp gần nhất.
RegExp[Symbol.species]-
Hàm constructor được dùng để tạo các đối tượng dẫn xuất.
Phương thức tĩnh
RegExp.escape()-
Escape bất kỳ ký tự cú pháp regex tiềm năng nào trong chuỗi, và trả về chuỗi mới có thể được sử dụng an toàn làm mẫu literal cho constructor
RegExp().
Thuộc tính instance
Các thuộc tính này được định nghĩa trên RegExp.prototype và được chia sẻ bởi tất cả các instance RegExp.
RegExp.prototype.constructor-
Hàm constructor đã tạo ra đối tượng instance. Đối với các instance
RegExp, giá trị khởi tạo là constructorRegExp. RegExp.prototype.dotAll-
Liệu
.có so khớp ký tự xuống dòng hay không. RegExp.prototype.flags-
Chuỗi chứa các flags của đối tượng
RegExp. RegExp.prototype.global-
Liệu có kiểm tra biểu thức chính quy với tất cả các kết quả khớp có thể có trong chuỗi hay chỉ với kết quả đầu tiên.
RegExp.prototype.hasIndices-
Liệu kết quả biểu thức chính quy có hiển thị chỉ số bắt đầu và kết thúc của các chuỗi con được chụp hay không.
RegExp.prototype.ignoreCase-
Liệu có bỏ qua phân biệt chữ hoa chữ thường khi cố gắng so khớp trong chuỗi hay không.
RegExp.prototype.multiline-
Liệu có tìm kiếm trong chuỗi trên nhiều dòng hay không.
RegExp.prototype.source-
Văn bản của mẫu.
RegExp.prototype.sticky-
Liệu tìm kiếm có sticky hay không.
RegExp.prototype.unicode-
Liệu các tính năng Unicode có được bật hay không.
RegExp.prototype.unicodeSets-
Liệu flag
v, nâng cấp của chế độu, có được bật hay không.
Các thuộc tính này là thuộc tính riêng của mỗi instance RegExp.
lastIndex-
Chỉ số để bắt đầu tìm kiếm kết quả so khớp tiếp theo.
Phương thức instance
RegExp.prototype.compile()Deprecated-
(Tái-)biên dịch biểu thức chính quy trong quá trình thực thi script.
RegExp.prototype.exec()-
Thực thi tìm kiếm kết quả so khớp trong tham số chuỗi của nó.
RegExp.prototype.test()-
Kiểm tra kết quả so khớp trong tham số chuỗi của nó.
RegExp.prototype.toString()-
Trả về chuỗi biểu diễn đối tượng được chỉ định. Ghi đè phương thức
Object.prototype.toString(). RegExp.prototype[Symbol.match]()-
Thực hiện so khớp với chuỗi đã cho và trả về kết quả so khớp.
RegExp.prototype[Symbol.matchAll]()-
Trả về tất cả các kết quả so khớp của biểu thức chính quy với một chuỗi.
RegExp.prototype[Symbol.replace]()-
Thay thế các kết quả so khớp trong chuỗi đã cho bằng chuỗi con mới.
RegExp.prototype[Symbol.search]()-
Tìm kiếm kết quả so khớp trong chuỗi đã cho và trả về chỉ số mà mẫu được tìm thấy trong chuỗi.
RegExp.prototype[Symbol.split]()-
Tách chuỗi đã cho thành mảng bằng cách phân tách chuỗi thành các chuỗi con.
Ví dụ
>Sử dụng biểu thức chính quy để thay đổi định dạng dữ liệu
Script sau sử dụng phương thức String.prototype.replace() để so khớp tên theo định dạng họ tên và xuất ra theo định dạng tên, họ.
Trong văn bản thay thế, script sử dụng $1 và $2 để chỉ kết quả của các ngoặc đơn so khớp tương ứng trong mẫu biểu thức chính quy.
const re = /(\w+)\s(\w+)/;
const str = "Maria Cruz";
const newStr = str.replace(re, "$2, $1");
console.log(newStr);
Kết quả hiển thị là "Cruz, Maria".
Sử dụng biểu thức chính quy để tách dòng với các ký tự xuống dòng khác nhau
Ký tự xuống dòng mặc định khác nhau tùy theo nền tảng (Unix, Windows, v.v.). Cách tách dòng trong ví dụ này hoạt động trên tất cả các nền tảng.
const text = "Some text\nAnd some more\r\nAnd yet\nThis is the end";
const lines = text.split(/\r?\n/);
console.log(lines); // [ 'Some text', 'And some more', 'And yet', 'This is the end' ]
Lưu ý rằng thứ tự của các mẫu trong biểu thức chính quy quan trọng.
Sử dụng biểu thức chính quy trên nhiều dòng
Theo mặc định, ký tự . không so khớp ký tự xuống dòng. Để làm cho nó so khớp ký tự xuống dòng, hãy sử dụng flag s (chế độ dotAll).
const s = "Please yes\nmake my day!";
s.match(/yes.*day/);
// Returns null
s.match(/yes.*day/s);
// Returns ["yes\nmake my day"]
Sử dụng biểu thức chính quy với flag sticky
Flag sticky cho biết rằng biểu thức chính quy thực hiện so khớp sticky trong chuỗi đích bằng cách cố gắng so khớp bắt đầu từ RegExp.prototype.lastIndex.
const str = "#foo#";
const regex = /foo/y;
regex.lastIndex = 1;
regex.test(str); // true
regex.lastIndex = 5;
regex.test(str); // false (lastIndex is taken into account with sticky flag)
regex.lastIndex; // 0 (reset after match failure)
Sự khác biệt giữa flag sticky và flag global
Với flag sticky y, kết quả so khớp tiếp theo phải xảy ra tại vị trí lastIndex, trong khi với flag global g, kết quả so khớp có thể xảy ra tại vị trí lastIndex hoặc sau đó:
const re = /\d/y;
let r;
while ((r = re.exec("123 456"))) {
console.log(r, "AND re.lastIndex", re.lastIndex);
}
// [ '1', index: 0, input: '123 456', groups: undefined ] AND re.lastIndex 1
// [ '2', index: 1, input: '123 456', groups: undefined ] AND re.lastIndex 2
// [ '3', index: 2, input: '123 456', groups: undefined ] AND re.lastIndex 3
// … and no more match.
Với flag global g, tất cả 6 chữ số sẽ được so khớp, không chỉ 3.
Biểu thức chính quy và ký tự Unicode
\w và \W chỉ so khớp các ký tự dựa trên ASCII; ví dụ, a đến z, A đến Z, 0 đến 9, và _.
Để so khớp các ký tự từ các ngôn ngữ khác như Cyrillic hoặc Hebrew, hãy sử dụng \uHHHH, trong đó HHHH là giá trị Unicode của ký tự theo hệ thập lục phân.
Ví dụ này minh họa cách tách ký tự Unicode ra khỏi một từ.
const text = "Образец text на русском языке";
const regex = /[\u0400-\u04ff]+/g;
const match = regex.exec(text);
console.log(match[0]); // 'Образец'
console.log(regex.lastIndex); // 7
const match2 = regex.exec(text);
console.log(match2[0]); // 'на' (did not log 'text')
console.log(regex.lastIndex); // 15
// and so on
Tính năng Unicode property escapes cung cấp cách đơn giản hơn để nhắm mục tiêu vào các phạm vi Unicode cụ thể, bằng cách cho phép các câu lệnh như \p{scx=Cyrl} (để so khớp bất kỳ chữ Cyrillic nào), hoặc \p{L}/u (để so khớp một chữ cái từ bất kỳ ngôn ngữ nào).
Trích xuất tên subdomain từ URL
const url = "http://xxx.example.com";
console.log(/^https?:\/\/(.+?)\./.exec(url)[1]); // 'xxx'
Note: Thay vì sử dụng biểu thức chính quy để phân tích URL, thường tốt hơn khi sử dụng trình phân tích URL dựng sẵn của trình duyệt bằng cách sử dụng URL API.
Xây dựng biểu thức chính quy từ đầu vào động
const breakfasts = ["bacon", "eggs", "oatmeal", "toast", "cereal"];
const order = "Let me get some bacon and eggs, please";
order.match(new RegExp(`\\b(${breakfasts.join("|")})\\b`, "g"));
// Returns ['bacon', 'eggs']
Đặc tả kỹ thuật
| Specification |
|---|
| ECMAScript® 2027 Language Specification> # sec-regexp-regular-expression-objects> |
Tương thích trình duyệt
Ghi chú dành riêng cho Firefox
Bắt đầu từ Firefox 34, trong trường hợp nhóm chụp (capturing group) có quantifier ngăn nhóm đó thực thi, văn bản so khớp cho nhóm chụp bây giờ là undefined thay vì chuỗi rỗng:
// Firefox 33 or older
"x".replace(/x(.)?/g, (m, group) => {
console.log(`group: ${JSON.stringify(group)}`);
});
// group: ""
// Firefox 34 or newer
"x".replace(/x(.)?/g, (m, group) => {
console.log(`group: ${group}`);
});
// group: undefined
Lưu ý rằng do tính tương thích web, RegExp.$N vẫn sẽ trả về chuỗi rỗng thay vì undefined (bug 1053944).