ToolDeck

Kiểm tra Regex

Kiểm tra biểu thức chính quy với một chuỗi và xem tất cả kết quả khớp được tô sáng

Thử ví dụ

Biểu thức

//g

Chuỗi kiểm tra

Chạy cục bộ · An toàn để dán thông tin bí mật

Biểu thức chính quy là gì?

Biểu thức chính quy (regex hoặc regexp) là một chuỗi ký tự định nghĩa một mẫu tìm kiếm. Công cụ kiểm tra regex cho phép bạn viết một mẫu, chạy nó với văn bản mẫu và xem tất cả kết quả khớp được tô sáng theo thời gian thực. Khái niệm này bắt nguồn từ công trình của nhà toán học Stephen Kleene về ngôn ngữ chính quy vào những năm 1950, và Ken Thompson đã xây dựng engine regex đầu tiên vào trình soạn thảo văn bản QED năm 1968.

Một engine regex đọc mẫu từ trái sang phải, tiêu thụ các ký tự đầu vào khi cố khớp. Nó sử dụng backtracking khi một kết quả khớp một phần thất bại: engine lùi lại và thử các nhánh thay thế trong mẫu. Một số engine (như RE2 dùng trong Go) tránh hoàn toàn backtracking bằng cách chuyển đổi mẫu thành automata hữu hạn xác định (DFA), đảm bảo khớp theo thời gian tuyến tính nhưng không hỗ trợ các tính năng như back-reference.

Cú pháp regex được chuẩn hóa một cách lỏng lẻo. PCRE (Perl Compatible Regular Expressions) là dạng phổ biến nhất, được hỗ trợ bởi PHP, module re của Python và JavaScript với một số khác biệt nhỏ. POSIX định nghĩa một cú pháp hạn chế hơn được dùng bởi grep và sed. Những khác biệt này quan trọng khi chuyển mẫu giữa các ngôn ngữ: một lookahead hoạt động trong JavaScript có thể không biên dịch được trong engine RE2 của Go.

Tại sao dùng công cụ kiểm tra Regex trực tuyến?

Viết regex trong file code đòi hỏi phải lưu, chạy và kiểm tra kết quả mỗi lần bạn điều chỉnh mẫu. Một công cụ kiểm tra regex trên trình duyệt rút ngắn vòng phản hồi đó về zero: bạn gõ, bạn thấy kết quả khớp.

Tô sáng kết quả khớp theo thời gian thực
Mỗi lần gõ phím cập nhật kết quả khớp ngay lập tức. Bạn thấy phần nào của văn bản khớp, nhóm capture nào được điền và chính xác nơi mỗi kết quả bắt đầu và kết thúc. Không có chu kỳ biên dịch-chạy-gỡ lỗi.
🔒
Xử lý ưu tiên bảo mật
Khớp mẫu chạy trong trình duyệt của bạn bằng engine JavaScript RegExp. Không có văn bản hay mẫu nào được gửi lên máy chủ. Điều này quan trọng khi kiểm tra với file log, dữ liệu khách hàng hoặc phản hồi API chứa thông tin nhạy cảm.
🔍
Kiểm tra kết quả khớp trực quan
Kết quả khớp được tô sáng ngay trong văn bản cùng với vị trí và giá trị của các nhóm capture. Nhìn thấy kết quả khớp bằng mắt giúp dễ phát hiện lỗi off-by-one trong quantifier hoặc thiếu anchor.
🌐
Không cần đăng nhập hay cài đặt
Hoạt động trên mọi thiết bị có trình duyệt hiện đại. Không cần tài khoản, không cần extension, không cần plugin IDE. Mở trang, dán mẫu và văn bản của bạn, rồi bắt đầu kiểm tra.

Các trường hợp sử dụng công cụ kiểm tra Regex

Xác thực đầu vào phía frontend
Xây dựng và xác minh mẫu cho các trường email, số điện thoại hoặc thẻ tín dụng trước khi nhúng vào thuộc tính pattern của HTML5 hoặc logic xác thực JavaScript.
Phân tích log phía backend
Viết mẫu regex để trích xuất timestamp, mã lỗi hoặc địa chỉ IP từ log ứng dụng. Kiểm tra với mẫu log thực tế để xác nhận mẫu capture đúng nhóm.
DevOps & Hạ tầng
Gỡ lỗi regex dùng trong khối location của Nginx, quy tắc rewrite của Apache hoặc quy tắc alerting của Prometheus. Một mẫu sai trong cấu hình máy chủ có thể phá vỡ routing hoặc bỏ lỡ cảnh báo hoàn toàn.
QA & Tự động hóa kiểm tra
Xác thực rằng nội dung phản hồi hoặc đầu ra HTML khớp với mẫu mong đợi trong các assertion kiểm tra end-to-end. Kiểm tra regex ở đây trước khi commit vào bộ kiểm tra của bạn.
Pipeline trích xuất dữ liệu
Tạo mẫu để trích xuất các trường có cấu trúc từ văn bản phi cấu trúc: thu thập giá sản phẩm, phân tích các trường hợp ngoại lệ CSV hoặc lấy metadata từ header email.
Học biểu thức chính quy
Thử nghiệm với metacharacter, quantifier và nhóm trên các chuỗi mẫu. Phản hồi trực quan tức thì giúp học cú pháp regex dễ hơn nhiều so với chỉ đọc tài liệu.

Tham chiếu nhanh cú pháp Regex

Bảng dưới đây bao gồm các token regex được dùng nhiều nhất. Chúng hoạt động trên JavaScript, Python, Go, PHP và hầu hết các engine tương thích PCRE. Các extension theo ngôn ngữ (như conditional pattern của Python hoặc named group của JavaScript với cú pháp \k) được ghi chú trong phần ví dụ mã.

MẫuTênMô tả
.Any characterMatches any single character except newline (unless s flag is set)
\dDigitMatches [0-9]
\wWord characterMatches [a-zA-Z0-9_]
\sWhitespaceMatches space, tab, newline, carriage return, form feed
\bWord boundaryMatches the position between a word character and a non-word character
^Start of string/lineMatches the start of the input; with m flag, matches start of each line
$End of string/lineMatches the end of the input; with m flag, matches end of each line
*Zero or moreMatches the preceding token 0 or more times (greedy)
+One or moreMatches the preceding token 1 or more times (greedy)
?OptionalMatches the preceding token 0 or 1 time
{n,m}Quantifier rangeMatches the preceding token between n and m times
()Capturing groupGroups tokens and captures the matched text for back-references
(?:)Non-capturing groupGroups tokens without capturing the matched text
(?=)Positive lookaheadMatches a position followed by the given pattern, without consuming it
(?<=)Positive lookbehindMatches a position preceded by the given pattern, without consuming it
[abc]Character classMatches any one of the characters inside the brackets
[^abc]Negated classMatches any character not inside the brackets
|AlternationMatches the expression before or after the pipe

Giải thích các cờ Regex

Cờ (còn gọi là modifier) thay đổi cách engine xử lý mẫu. Trong JavaScript bạn thêm chúng sau dấu gạch chéo đóng: /pattern/gi. Trong Python bạn truyền chúng làm đối số thứ hai: re.findall(pattern, text, re.IGNORECASE | re.MULTILINE). Không phải tất cả cờ đều có sẵn trong mọi ngôn ngữ.

CờTênHành vi
gGlobalFind all matches, not just the first one
iCase-insensitiveLetters match both uppercase and lowercase
mMultiline^ and $ match start/end of each line, not just the whole string
sDot-all. matches newline characters as well
uUnicodeTreat the pattern and subject as a Unicode string; enables \u{FFFF} syntax
yStickyMatches only from the lastIndex position in the target string

Ví dụ mã

Các ví dụ regex thực tế trong JavaScript, Python, Go và dòng lệnh. Mỗi ví dụ minh họa cách xây dựng mẫu, trích xuất kết quả khớp và đầu ra.

JavaScript
// Match all email addresses in a string
const text = 'Contact us at support@example.com or sales@example.com'
const emailRegex = /[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/g

const matches = text.matchAll(emailRegex)
for (const match of matches) {
  console.log(match[0], 'at index', match.index)
}
// → "support@example.com" at index 14
// → "sales@example.com" at index 37

// Named capture groups (ES2018+)
const dateRegex = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/
const result = '2026-03-30'.match(dateRegex)
console.log(result.groups)
// → { year: "2026", month: "03", day: "30" }

// Replace with a callback
'hello world'.replace(/\b\w/g, c => c.toUpperCase())
// → "Hello World"
Python
import re

# Find all IPv4 addresses
text = 'Server 192.168.1.1 responded, fallback to 10.0.0.255'
pattern = r'\b(?:\d{1,3}\.){3}\d{1,3}\b'

matches = re.findall(pattern, text)
print(matches)  # → ['192.168.1.1', '10.0.0.255']

# Named groups and match objects
date_pattern = r'(?P<year>\d{4})-(?P<month>\d{2})-(?P<day>\d{2})'
m = re.search(date_pattern, 'Released on 2026-03-30')
if m:
    print(m.group('year'))   # → '2026'
    print(m.group('month'))  # → '03'

# Compile for repeated use (faster in loops)
compiled = re.compile(r'\b[A-Z][a-z]+\b')
words = compiled.findall('Hello World Foo bar')
print(words)  # → ['Hello', 'World', 'Foo']
Go
package main

import (
	"fmt"
	"regexp"
)

func main() {
	// Find all matches
	re := regexp.MustCompile(`\b[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}\b`)
	text := "Contact support@example.com or sales@example.com"
	matches := re.FindAllString(text, -1)
	fmt.Println(matches)
	// → [support@example.com sales@example.com]

	// Named capture groups
	dateRe := regexp.MustCompile(`(?P<year>\d{4})-(?P<month>\d{2})-(?P<day>\d{2})`)
	match := dateRe.FindStringSubmatch("2026-03-30")
	for i, name := range dateRe.SubexpNames() {
		if name != "" {
			fmt.Printf("%s: %s\n", name, match[i])
		}
	}
	// → year: 2026
	// → month: 03
	// → day: 30

	// Replace with a function
	result := re.ReplaceAllStringFunc(text, func(s string) string {
		return "[REDACTED]"
	})
	fmt.Println(result)
	// → Contact [REDACTED] or [REDACTED]
}
CLI (grep / sed)
# Find lines matching an IP address pattern
grep -E '\b([0-9]{1,3}\.){3}[0-9]{1,3}\b' access.log

# Extract email addresses from a file
grep -oE '[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}' contacts.txt

# Replace dates from YYYY-MM-DD to DD/MM/YYYY using sed
echo "2026-03-30" | sed -E 's/([0-9]{4})-([0-9]{2})-([0-9]{2})/\3\/\2\/\1/'
# → 30/03/2026

# Count matches per file in a directory
grep -rcE 'TODO|FIXME|HACK' src/
# → src/main.js:3
# → src/utils.js:1

Câu hỏi thường gặp

Sự khác biệt giữa regex và glob pattern là gì?
Glob pattern (như *.txt hoặc src/**/*.js) là cú pháp wildcard đơn giản dùng để khớp đường dẫn file trong shell và build tool. Chúng hỗ trợ * (bất kỳ ký tự nào), ? (một ký tự) và [] (lớp ký tự) nhưng thiếu quantifier, nhóm, lookahead và alternation. Regex biểu đạt phong phú hơn nhiều và hoạt động trên văn bản tùy ý, không chỉ đường dẫn file. Glob pattern *.json tương đương gần với regex ^.*\.json$.
Làm thế nào để khớp một dấu chấm hoặc dấu ngoặc vuông theo nghĩa đen trong regex?
Thêm dấu backslash trước ký tự: \. khớp một dấu chấm theo nghĩa đen, \[ khớp một dấu ngoặc vuông theo nghĩa đen. Bên trong lớp ký tự [], dấu chấm đã là nghĩa đen và không cần thoát. Lỗi phổ biến là viết 192.168.1.1 mà không thoát các dấu chấm, khiến nó khớp cả 192x168y1z1 vì . có nghĩa là "bất kỳ ký tự nào".
Dữ liệu kiểm tra của tôi có được gửi lên máy chủ không?
Không. Công cụ này thực thi khớp regex hoàn toàn trong trình duyệt của bạn bằng engine JavaScript RegExp. Không có yêu cầu mạng nào được thực hiện với văn bản hoặc mẫu của bạn. Bạn có thể xác nhận điều này bằng cách mở tab Network trong DevTools của trình duyệt khi sử dụng công cụ.
Tại sao regex của tôi hoạt động trong JavaScript nhưng lại lỗi trong Python?
JavaScript và Python sử dụng các engine regex khác nhau với tập tính năng hơi khác nhau. JavaScript hỗ trợ \d, lookahead (?=) và lookbehind (?<=) từ ES2018, nhưng không hỗ trợ conditional pattern, atomic group hoặc possessive quantifier. Module re của Python không hỗ trợ lớp thuộc tính Unicode \p{\}' (dùng module regex của bên thứ ba thay thế). Luôn kiểm tra trong engine của ngôn ngữ mục tiêu hoặc tham khảo tài liệu regex của ngôn ngữ đó.
Điều gì gây ra catastrophic backtracking trong regex?
Catastrophic backtracking xảy ra khi một mẫu có quantifier lồng nhau tạo ra số lượng đường khớp theo cấp số nhân. Ví dụ điển hình là (a+)+ áp dụng cho một chuỗi các ký tự 'a' theo sau là một ký tự không khớp. Engine thử mọi cách có thể để phân chia các ký tự 'a' giữa nhóm bên trong và bên ngoài trước khi thất bại. Khắc phục bằng cách dùng atomic group (?>), possessive quantifier a++ hoặc viết lại mẫu để tránh lặp lại không rõ ràng.
Tôi có thể dùng regex để phân tích HTML không?
Regex có thể trích xuất các giá trị đơn giản từ đoạn HTML, như lấy href từ một thẻ <a> đơn lẻ. Để phân tích HTML đầy đủ, hãy dùng parser phù hợp (DOMParser trong JavaScript, BeautifulSoup trong Python hoặc html/template trong Go). HTML là ngữ pháp phi ngữ cảnh, còn regex xử lý ngữ pháp chính quy. Các thẻ lồng nhau, thuộc tính tùy chọn và phần tử tự đóng tạo ra các mẫu mà regex không thể khớp một cách đáng tin cậy.
Sự khác biệt giữa greedy và lazy quantifier là gì?
Greedy quantifier (* hoặc +) khớp nhiều ký tự nhất có thể, sau đó backtrack nếu phần còn lại của mẫu thất bại. Lazy quantifier (*? hoặc +?) khớp ít ký tự nhất có thể, chỉ mở rộng khi cần. Với đầu vào <b>one</b><b>two</b>, mẫu greedy <b>.*</b> khớp toàn bộ chuỗi từ <b> đầu tiên đến </b> cuối cùng, trong khi mẫu lazy <b>.*?</b> khớp riêng biệt <b>one</b> và <b>two</b>.