Regex
Duy Văn | 12/03/2025
Regex là một công cụ rất mạnh dành cho việc xử lý các chuỗi dài với các tác vụ tìm kiếm và thay thế từ
Java không có built-in regex mà sẽ sử dụng package java.util.regex với 3 class chính:
- Pattern class - định nghĩa pattern để tìm kiếm
- Matcher class - thực hiện tìm kiếm
- PatternSyntaxException class - class Exception khi lỗi syntax trong pattern
Việc triển khai regex sẽ luôn cần sử dụng cả 2 class là Pattern và Matcher
import java.util.regex.Matcher;
import java.util.regex.Pattern;
Ví dụ cho một string “Hello World” và chúng ta muốn tìm kiếm từ “Hello” trong string đó
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Main {
public static void main(String[] args) {
String text = "Hello World";
String pattern = "Hello";
Pattern p = Pattern.compile(pattern);
Matcher m = p.matcher(text);
System.out.println(m.find());
}
}
Đầu tiên, Pattern.compile() sẽ tạo ra pattern dùng để tìm kiếm, chúng ta có thể để như trên, tức là tìm chính xác “Hello”, hoặc Pattern.compile(pattern, Pattern.CASE_INSENSITIVE); để tìm kiếm không phân biệt chữ hoa chữ thường
matcher() method của class Match sẽ tìm kiếm pattern trong string, nó trả ra một object Matcher chứa thuộc tính liên quan
find() method của object Matcher trả ra boolean rằng pattern có được tìm thấy hay không
Để lấy giá trị tìm được, chúng ta sử dụng group() method của object Matcher
import java.util.regex.Matcher;
public class Main {
public static void main(String[] args) {
String text = "Hello World";
String pattern = "Hello";
Pattern p = Pattern.compile(pattern);
Matcher m = p.matcher(text);
if (m.find()) {
System.out.println(m.group());
}
}
}
Bắt buộc phải gọi find() trước khi gọi group() nếu không sẽ báo lỗi, vì find() ngoại trừ trả ra true hay false, bản chất của nó chính là thực hiện tìm kiếm, không tìm kiếm thì lấy đâu ra kết quả?
Flags của compile()
Khi sử dụng compile() để tạo pattern, có 3 flag chính để xác định cách pattern sẽ tìm kiếm:
Pattern.CASE_INSENSITIVE- không phân biệt chữ hoa chữ thườngPattern.LITERAL- các ký tự đặc biệt trong pattern sẽ được coi là ký tự bình thườngPattern.UNICODE_CASE- không phân biệt chữ hoa chữ thường khi sử dụng cùng vớiPattern.CASE_INSENSITIVE
Pattern p = Pattern.compile(pattern, Pattern.CASE_INSENSITIVE);
Pattern p = Pattern.compile(pattern, Pattern.LITERAL);
Pattern p = Pattern.compile(pattern
, Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE);
Pattern thường gặp
Để sử dụng vào param đầu tiên của compile(), chúng ta cần phải biết một số pattern thường gặp:
[abc]- a, b hoặc c - tìm kiếm các ký tự trong dấu ngoặc vuông[^abc]- không phải a, b hoặc c - tìm kiếm các ký tự không nằm trong dấu ngoặc vuông[a-z]- a đến z[A-Z]- A đến Z[0-9]- 0 đến 9[a-zA-Z]- a đến z hoặc A đến Z
Metacharacters
Các metacharacters là các ký tự đặc biệt trong regex, chúng ta cần phải escape chúng nếu muốn tìm kiếm chính xác chúng:
.- tìm chỉ 1 lần xuất hiện bất kỳ ký tự nào|- tìm kiếm 1 trong các pattern tách bởi dấu|- ví dụa|bsẽ tìm kiếmahoặcb^- tìm kiếm từ đầu chuỗi$- tìm kiếm từ cuối chuỗi\d- tìm kiếm số\s- tìm kiếm khoảng trắng\b- tìm kiếm từ đầu hoặc cuối từ - ví dụ\bWORDsẽ tìm được cả WORDS và WORD, cònWORD\bsẽ tìm được chỉ WORD\uxxxx- tìm kiếm ký tự unicode- ví dụ\u0041sẽ tìm kiếm ký tựA
Quantifiers
Quantifiers là các ký tự để xác định số lần xuất hiện của pattern:
*- 0 hoặc nhiều lần - ví dụa*sẽ tìm đượca,aa,aaa,…+- 1 hoặc nhiều lần - ví dụa+sẽ tìm đượca,aa,aaa,…?- 0 hoặc 1 lần - ví dụa?sẽ tìm đượcahoặc không tìm được gì{n}- chính xác n lần - ví dụa{2}sẽ tìm đượcaa{n,}- ít nhất n lần - ví dụa{2,}sẽ tìm đượcaa,aaa,…{n,m}- từ n đến m lần - ví dụa{2,4}sẽ tìm đượcaa,aaa,aaaa