Lớp Pattern (Class Pattern)
Lớp Pattern trong Java đóng vai trò như một mẫu khuôn (template) cho một biểu thức chính quy. Một biểu thức chính quy, được chỉ định dưới dạng một chuỗi. Khi bạn có một chuỗi biểu thức chính quy, bạn sẽ biên dịch nó thành một đối tượng Pattern. Đối tượng Pattern này sau đó được sử dụng để tạo các đối tượng Matcher, và các Matcher này sẽ thực hiện việc tìm kiếm và so khớp trên các chuỗi văn bản.
Một trình tự gọi điển hình như sau:
Ví dụ
Pattern p = Pattern.compile("a*b");
Matcher m = p.matcher("aaaaab");
boolean b = m.matches();
Phương thức matches là một cách nhanh chóng để kiểm tra xem một chuỗi có khớp với một biểu thức chính quy không, nhưng chỉ nên dùng khi bạn chỉ cần kiểm tra một lần.
Phương thức này tự động biên dịch biểu thức chính quy và thực hiện kiểm tra.
Nếu bạn cần kiểm tra nhiều lần, tốt hơn nên tạo một đối tượng Pattern và Matcher để tăng hiệu suất.
Lớp Pattern là an toàn để sử dụng trong nhiều luồng cùng lúc.
Lớp Matcher không an toàn cho việc sử dụng trong nhiều luồng cùng lúc.
Tóm lại:
↳ Sử dụng Pattern.matches() cho các kiểm tra đơn giản, nhanh chóng.
↳ Sử dụng Pattern và Matcher cho các kiểm tra phức tạp hoặc lặp lại để tăng hiệu suất.
↳ Luôn chú ý đến sự an toàn khi sử dụng các đối tượng trong môi trường đa luồng.
Ⅰ. Khai báo lớp Pattern trong Java
Để sử dụng lớp Pattern trong gói java.util.regex, bạn cần thêm câu lệnh import vào đầu file Java của mình.
Cú pháp câu lệnh import:
Cú pháp
import java.util.regex.Pattern;
Cú pháp khai báo lớp Pattern:
Cú pháp
public final class Pattern
extends Object
implements Serializable
Dưới đây là giải thích chi tiết về cú pháp khai báo này:
↳ public: Lớp này có thể được truy cập từ bất kỳ đâu trong chương trình, không bị giới hạn phạm vi.
↳ final: Lớp này không thể bị kế thừa. Điều này có nghĩa là bạn không thể tạo một lớp con từ Pattern.
↳ class Pattern: Đây là khai báo của lớp Pattern, lớp này đại diện cho biểu thức chính quy (regular expression) trong Java. Pattern cung cấp các phương thức để biên dịch, kiểm tra và làm việc với biểu thức chính quy, giúp bạn thực hiện các thao tác tìm kiếm, thay thế và phân tích chuỗi văn bản.
↳ extends Object: Tất cả các lớp trong Java đều kế thừa từ lớp Object (lớp gốc của tất cả các lớp trong Java). Việc này cho phép lớp Pattern kế thừa các phương thức cơ bản từ Object, chẳng hạn như toString(), equals(), và hashCode().
↳ implements Serializable: Từ khóa implements cho biết lớp Pattern triển khai giao diện Serializable. Giao diện Serializable cho phép các đối tượng của lớp Pattern có thể được chuyển đổi thành dòng byte để lưu trữ hoặc truyền qua mạng (serialization). Điều này là cần thiết khi bạn muốn lưu trạng thái của đối tượng hoặc truyền đối tượng qua các ranh giới mạng.
Ⅱ. Các trường (Fields) của lớp Pattern
Các trường (Fields) là những giá trị số nguyên được sử dụng để thay đổi cách thức hoạt động của biểu thức chính quy. Chúng được định nghĩa trong lớp Pattern và có thể được kết hợp với nhau bằng phép toán OR (|) để tạo ra các trường (Fields) tùy chỉnh.
↳ static final int CANON_EQ: Kích hoạt tính tương đương chính tắc (canonical equivalence).
↳ static final int CASE_INSENSITIVE: Kích hoạt việc khớp không phân biệt chữ hoa chữ thường.
↳ static final int COMMENTS: Cho phép sử dụng khoảng trắng và chú thích trong mẫu biểu thức chính quy.
↳ static final intDOTALL: Kích hoạt chế độ dotall, cho phép ký tự . khớp với mọi ký tự, bao gồm cả ký tự xuống dòng.
↳ static final intLITERAL: Kích hoạt phân tích cú pháp kiểu literal của mẫu (mẫu sẽ được xem như là chuỗi chính xác).
↳ static final int MULTILINE: Kích hoạt chế độ nhiều dòng, thay đổi cách ký tự ^ và $ khớp với các dòng trong chuỗi.
↳ static final int UNICODE_CASE: Kích hoạt việc gập chữ theo chuẩn Unicode.
↳ static final int UNICODE_CHARACTER_CLASS: Kích hoạt phiên bản Unicode của các lớp ký tự được định nghĩa sẵn và lớp ký tự POSIX.
↳ static final intUNIX_LINES: Kích hoạt chế độ dòng Unix, thay đổi cách ký tự . khớp với ký tự xuống dòng (\n).
Ⅲ. Phương thức của lớp Pattern
Lớp Pattern trong Java là một lớp đại diện cho một biểu thức chính quy đã được biên dịch. Nó cung cấp các phương thức để tạo các đối tượng Matcher và thực hiện các phép toán liên quan đến biểu thức chính quy. Dưới đây là các phương thức chính trong lớp Pattern:
↳ Predicate<String> asMatchPredicate():Tạo một predicate (biểu thức điều kiện) để kiểm tra xem mẫu biểu thức chính quy này có khớp với chuỗi đầu vào không.
↳ Predicate<String> asPredicate(): Tạo một predicate (biểu thức điều kiện) để kiểm tra xem mẫu biểu thức chính quy này có xuất hiện trong chuỗi đầu vào không.
↳ static Pattern compile(String regex): Biên dịch biểu thức chính quy được cung cấp thành một mẫu (pattern).
↳ static Pattern compile(String regex, int flags): Biên dịch biểu thức chính quy được cung cấp thành một mẫu (pattern) với các cờ (flags) được chỉ định.
↳ int flags(): Trả về các cờ (flags) của mẫu biểu thức chính quy này.
↳ Matcher matcher(CharSequence input): Tạo một đối tượng Matcher để kiểm tra xem chuỗi đầu vào có khớp với mẫu biểu thức chính quy này không.
↳ static boolean matches(String regex, CharSequence input): Biên dịch biểu thức chính quy được cung cấp và thử khớp chuỗi đầu vào với nó.
↳ String pattern(): Trả về biểu thức chính quy từ mẫu biểu thức chính quy này.
↳ static String quote(String s): Trả về một chuỗi mẫu chính quy literal cho chuỗi được chỉ định, tức là nó tạo ra một mẫu chính quy mà các ký tự đặc biệt được xem như ký tự bình thường.
↳ String[] split(CharSequence input): Chia chuỗi đầu vào quanh các khớp của mẫu biểu thức chính quy này và trả về một mảng các chuỗi.
↳ String[] split(CharSequence input, int limit): Chia chuỗi đầu vào quanh các khớp của mẫu biểu thức chính quy này với giới hạn số lượng phần tử trả về và trả về một mảng các chuỗi.
↳ Stream<String> splitAsStream(CharSequence input): Tạo một stream từ chuỗi đầu vào quanh các khớp của mẫu biểu thức chính quy này.
↳ String toString(): Trả về đại diện chuỗi của mẫu biểu thức chính quy này.
Ⅳ. Tóm tắt các cấu trúc biểu thức chính quy
Biểu thức chính quy (Regular Expression - Regex) là một công cụ mạnh mẽ để tìm kiếm, so khớp và xử lý chuỗi ký tự theo mẫu nhất định. Chúng được sử dụng rộng rãi trong lập trình, xử lý văn bản và kiểm tra dữ liệu đầu vào. Dưới đây là các cấu trúc quan trọng giúp bạn hiểu và áp dụng biểu thức chính quy một cách hiệu quả.
1. Ký tự (Characters)
Cấu trúc (Construct) | Khớp (Matches) |
---|---|
x | Ký tự x |
\\ | Ký tự dấu gạch chéo ngược |
\0n | Ký tự có giá trị bát phân 0n (0 <= n <= 7) |
\0nn | Ký tự có giá trị bát phân 0nn (0 <= n <= 7) |
\0mnn | Ký tự có giá trị bát phân 0mnn (0 <= m <= 3, 0 <= n <= 7) |
\xhh | Ký tự có giá trị thập lục phân 0xhh |
\uhhhh | Ký tự có giá trị thập lục phân 0xhhhh |
\x{h...h} | Ký tự có giá trị thập lục phân 0xh...h (Ký tự.MIN_CODE_POINT <= 0xh...h <= Ký tự.MAX_CODE_POINT) |
\N{name} | Ký tự có tên ký tự Unicode 'name' |
\t | Ký tự tab ('\u0009') |
\n | Ký tự xuống dòng ('\u000A') |
\r | Ký tự trả về đầu dòng ('\u000D') |
\f | Ký tự nạp biểu mẫu ('\u000C') |
\a | Ký tự cảnh báo (chuông) ('\u0007') |
\e | Ký tự thoát ('\u001B') |
\cx | Ký tự điều khiển tương ứng với x |
Dưới đây là một số ví dụ minh họa cho các loại ký tự đã liệt kê trong biểu thức chính quy:
Ví dụ: Example.java
import java.util.regex.Pattern;
public class Example {
public static void main(String[] args) {
// Ví dụ 1: Ký tự cụ thể
String regexChar = "x";
String inputChar = "x";
boolean matchesChar = Pattern.matches(regexChar, inputChar);
System.out.println("Ký tự 'x' khớp với chuỗi 'x': " + matchesChar);
// Ví dụ 2: Dấu gạch chéo ngược
String regexBackslash = "\\\\";
String inputBackslash = "\\";
boolean matchesBackslash = Pattern.matches(regexBackslash, inputBackslash);
System.out.println("Dấu gạch chéo ngược '\\\\' khớp với chuỗi '\\': " + matchesBackslash);
// Ví dụ 3: Ký tự bát phân
String regexOctal = "\\0" + "7";
String inputOctal = "\u0007"; // Ký tự cảnh báo (bell)
boolean matchesOctal = Pattern.matches(regexOctal, inputOctal);
System.out.println("Ký tự bát phân '\0" + "7' khớp với ký tự cảnh báo (bell): " + matchesOctal);
// Ví dụ 4: Ký tự thập lục phân
String regexHex = "\\x41"; // 'A' trong hệ thập lục phân
String inputHex = "A";
boolean matchesHex = Pattern.matches(regexHex, inputHex);
System.out.println("Ký tự thập lục phân '\\x41' khớp với chuỗi 'A': " + matchesHex);
// Ví dụ 5: Ký tự Unicode
String regexUnicode = "\\N{LATIN CAPITAL LETTER A}";
String inputUnicode = "A"; // Đoạn mã Unicode cho 'A'
boolean matchesUnicode = Pattern.matches(regexUnicode, inputUnicode);
System.out.println("Ký tự Unicode '\\N{LATIN CAPITAL LETTER A}' khớp với chuỗi 'A': " + matchesUnicode);
// Ví dụ 6: Ký tự tab
String regexTab = "\\t";
String inputTab = "\t";
boolean matchesTab = Pattern.matches(regexTab, inputTab);
System.out.println("Ký tự tab '\\t' khớp với ký tự tab: " + matchesTab);
// Ví dụ 7: Ký tự xuống dòng
String regexNewline = "\\n";
String inputNewline = "\n";
boolean matchesNewline = Pattern.matches(regexNewline, inputNewline);
System.out.println("Ký tự xuống dòng '\\n' khớp với ký tự xuống dòng: " + matchesNewline);
// Ví dụ 8: Ký tự trả về đầu dòng
String regexCarriageReturn = "\\r";
String inputCarriageReturn = "\r";
boolean matchesCarriageReturn = Pattern.matches(regexCarriageReturn, inputCarriageReturn);
System.out.println("Ký tự trả về đầu dòng '\\r' khớp với ký tự trả về đầu dòng: " + matchesCarriageReturn);
// Ví dụ 9: Ký tự nạp biểu mẫu
String regexFormFeed = "\\f";
String inputFormFeed = "\f";
boolean matchesFormFeed = Pattern.matches(regexFormFeed, inputFormFeed);
System.out.println("Ký tự nạp biểu mẫu '\\f' khớp với ký tự nạp biểu mẫu: " + matchesFormFeed);
// Ví dụ 10: Ký tự cảnh báo (chuông)
String regexBell = "\\a";
String inputBell = "\u0007";
boolean matchesBell = Pattern.matches(regexBell, inputBell);
System.out.println("Ký tự cảnh báo (chuông) '\\a' khớp với ký tự cảnh báo: " + matchesBell);
// Ví dụ 11: Ký tự thoát
String regexEscape = "\\e";
String inputEscape = "\u001B"; // Ký tự thoát (escape)
boolean matchesEscape = Pattern.matches(regexEscape, inputEscape);
System.out.println("Ký tự thoát '\\e' khớp với ký tự thoát: " + matchesEscape);
// Ví dụ 12: Ký tự điều khiển
String regexControl = "\\cC";
String inputControl = "\u0003"; // Ký tự điều khiển (Ctrl+C)
boolean matchesControl = Pattern.matches(regexControl, inputControl);
System.out.println("Ký tự điều khiển '\\cC' khớp với ký tự điều khiển (Ctrl+C): " + matchesControl);
}
}
Kết quả của chương trình là:
Dấu gạch chéo ngược '\\' khớp với chuỗi '\': true
Ký tự bát phân '\07' khớp với ký tự cảnh báo (bell): true
Ký tự thập lục phân '\x41' khớp với chuỗi 'A': true
Ký tự Unicode '\N{LATIN CAPITAL LETTER A}' khớp với chuỗi 'A': true
Ký tự tab '\t' khớp với ký tự tab: true
Ký tự xuống dòng '\n' khớp với ký tự xuống dòng: true
Ký tự trả về đầu dòng '\r' khớp với ký tự trả
về đầu dòng: true
Ký tự nạp biểu mẫu '\f' khớp với ký tự nạp biểu mẫu: true
Ký tự cảnh báo (chuông) '\a' khớp với ký tự cảnh báo: true
Ký tự thoát '\e' khớp với ký tự thoát: true
Ký tự điều khiển '\cC' khớp với ký tự điều khiển (Ctrl+C): true
Hy vọng rằng những ví dụ trên đã giúp bạn hiểu rõ hơn về cách sử dụng các loại ký tự trong biểu thức chính quy.
2. Lớp ký tự (Character classes)
Cấu trúc (Construct) | Khớp (Matches) |
---|---|
[abc] | Các ký tự a, b, hoặc c (lớp ký tự đơn giản). |
[^abc] | Bất kỳ ký tự nào ngoại trừ a, b, hoặc c (phủ định). |
[a-zA-Z] | Từ a đến z hoặc từ A đến Z (dải ký tự). |
[a-d[m-p]] | Từ a đến d, hoặc từ m đến p (hợp nhất). |
[a-z&&[def]] | Các ký tự d, e, hoặc f (giao nhau). |
[a-z&&[^bc]] | Từ a đến z, trừ b và c (trừ). |
[a-z&&[^m-p]] | Từ a đến z, không bao gồm từ m đến p (trừ). |
Dưới đây là ví dụ về cách sử dụng các lớp ký tự trong Java bằng cách sử dụng lớp Pattern và Matcher. Ví dụ này sẽ kiểm tra các chuỗi với các mẫu khác nhau dựa trên lớp ký tự:
Ví dụ: Example.java
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Example {
public static void main(String[] args) {
String input = "abc def ghijklmnopqrstuvwxyz ABC DEFGHIJKLMNOPQRSTUVWXYZ";
// Mẫu và mô tả
String[] patterns = {
"[abc]", // Các ký tự a, b, hoặc c
"[^abc]", // Bất kỳ ký tự nào ngoại trừ a, b, hoặc c
"[a-zA-Z]", // Từ a đến z hoặc từ A đến Z
"[a-d[m-p]]", // Từ a đến d, hoặc từ m đến p
"[a-z&&[def]]", // Các ký tự d, e, hoặc f
"[a-z&&[^bc]]", // Từ a đến z, trừ b và c
"[a-z&&[^m-p]]" // Từ a đến z, không bao gồm từ m đến p
};
// Thực hiện kiểm tra cho mỗi mẫu
for (String patternStr : patterns) {
// Biên dịch mẫu
Pattern pattern = Pattern.compile(patternStr);
Matcher matcher = pattern.matcher(input);
System.out.println("Mẫu: " + patternStr);
// Tìm và in ra các kết quả khớp
while (matcher.find()) {
System.out.println("Khớp: " + matcher.group());
}
System.out.println();
}
}
}
Kết quả của chương trình là:
Khớp: a
Khớp: b
...
Khớp: w
Khớp: x
Khớp: y
Khớp: z
Hy vọng rằng những ví dụ trên đã giúp bạn hiểu rõ hơn về cách sử dụng các lớp ký tự trong biểu thức chính quy.
3. Các lớp ký tự được xác định trước (Predefined character classes)
Cấu trúc (Construct) | Khớp (Matches) |
---|---|
. | Bất kỳ ký tự nào (có thể hoặc không thể khớp với ký tự kết thúc dòng). |
\d | Một chữ số: [0-9]. |
\D | Một ký tự không phải chữ số: [^0-9]. |
\h | Một ký tự khoảng trắng nằm ngang: [ \t\xA0\u1680\u180e\u2000-\u200a\u202f\u205f\u3000]. |
\H | Một ký tự khoảng trắng không nằm ngang: [^\h]. |
\s | Một ký tự khoảng trắng: [ \t\n\x0B\f\r]. |
\S | Một ký tự không phải khoảng trắng: [^\s]. |
\v | Một ký tự khoảng trắng nằm dọc: [\n\x0B\f\r\x85\u2028\u2029]. |
\V | Một ký tự khoảng trắng không nằm dọc: [^\v]. |
\w | Một ký tự từ: [a-zA-Z_0-9]. |
\W | Một ký tự không phải từ: [^\w]. |
Dưới đây là ví dụ về cách sử dụng các lớp ký tự được xác định trước trong Java bằng cách sử dụng lớp Pattern và Matcher. Ví dụ này sẽ kiểm tra các chuỗi với các mẫu khác nhau dựa trên các lớp ký tự được xác định trước:
Ví dụ: Example.java
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Example {
public static void main(String[] args) {
String input = "Hello 123, world! \t\n New Line \u2000 Horizontal space \u2028 Vertical space";
// Mẫu và mô tả
String[] patterns = {
".", // Bất kỳ ký tự nào (có thể hoặc không khớp với ký tự kết thúc dòng)
"\\d", // Một chữ số: [0-9]
"\\D", // Một ký tự không phải chữ số: [^0-9]
"\\h", // Một ký tự khoảng trắng nằm ngang
"\\H", // Một ký tự khoảng trắng không nằm ngang
"\\s", // Một ký tự khoảng trắng: [ \t\n\x0B\f\\r]
"\\S", // Một ký tự không phải khoảng trắng: [^\s]
"\\v", // Một ký tự khoảng trắng nằm dọc
"\\V", // Một ký tự khoảng trắng không nằm dọc
"\\w", // Một ký tự từ: [a-zA-Z_0-9]
"\\W" // Một ký tự không phải từ: [^\w]
};
// Thực hiện kiểm tra cho mỗi mẫu
for (String patternStr : patterns) {
// Biên dịch mẫu
Pattern pattern = Pattern.compile(patternStr);
Matcher matcher = pattern.matcher(input);
System.out.println("Mẫu: " + patternStr);
// Tìm và in ra các kết quả khớp
while (matcher.find()) {
System.out.println("Khớp: " + matcher.group());
}
System.out.println();
}
}
}
Kết quả của chương trình là:
Khớp: H
Khớp: e
Khớp: l
....
Khớp:
Khớp:
Khớp:
Hy vọng rằng những ví dụ trên đã giúp bạn hiểu rõ hơn về cách sử dụng các lớp ký tự được xác định trước trong biểu thức chính quy.
4. Các lớp ký tự POSIX (chỉ dành cho US-ASCII)
Cấu trúc (Construct) | Khớp (Matches) |
---|---|
\p{Lower} | Ký tự chữ cái viết thường: [a-z]. |
\p{Upper} | Ký tự chữ cái viết hoa: [A-Z]. |
\p{ASCII} | Tất cả ký tự ASCII: [\x00-\x7F]. |
\p{Alpha} | Ký tự chữ cái (cả viết thường và viết hoa): [\p{Lower}\p{Upper} ]. |
\p{Digit} | Ký tự số thập phân: [0-9]. |
\p{Alnum} | Ký tự chữ cái hoặc số: [\p{Alpha}\p{Digit}]. |
\p{Punct} | Ký tự dấu câu: Một trong các ký tự "!"#$%&'()*+,-./:;<=>?@[\]^_{|}~`". |
\p{Graph} | Ký tự hiển thị: [\p{Alnum}\p{Punct}]. |
\p{Print} | Ký tự có thể in được: [\p{Graph}\x20] (bao gồm ký tự hiển thị và khoảng trắng). |
\p{Blank} | Một ký tự khoảng trắng hoặc tab: [ \t]. |
\p{Cntrl} | Ký tự điều khiển: [\x00-\x1F\x7F]. |
\p{XDigit} | Ký tự số hexa: [0-9a-fA-F]. |
\p{Space} | Ký tự khoảng trắng: [ \t\n\x0B\f\r]. |
Dưới đây là ví dụ về cách sử dụng các lớp ký tự POSIX trong Java với lớp Pattern và Matcher. Ví dụ này kiểm tra một chuỗi đầu vào để tìm các ký tự tương ứng với từng lớp ký tự POSIX đã được liệt kê:
Ví dụ: Example.java
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Example {
public static void main(String[] args) {
String input = "Hello 123, World! \t\n Special characters: !@# $%^ &*()_+";
// Mẫu và mô tả
String[] patterns = {
"\\p{Lower}", // Ký tự chữ cái viết thường: [a-z]
"\\p{Upper}", // Ký tự chữ cái viết hoa: [A-Z]
"\\p{ASCII}", // Tất cả ký tự ASCII: [\x00-\x7F]
"\\p{Alpha}", // Ký tự chữ cái (cả viết thường và viết hoa): [\\p{Lower}\\p{Upper}]
"\\p{Digit}", // Ký tự số thập phân: [0-9]
"\\p{Alnum}", // Ký tự chữ cái hoặc số: [\\p{Alpha}\\p{Digit}]
"\\p{Punct}", // Ký tự dấu câu: Một trong các ký tự "!"#$%&'()*+,-./:;<=>?@[\\]^_{|}~"
"\\p{Graph}", // Ký tự hiển thị: [\\p{Alnum}\\p{Punct}]
"\\p{Print}", // Ký tự có thể in được: [\\p{Graph}\x20]
"\\p{Blank}", // Một ký tự khoảng trắng hoặc tab: [ \t]
"\\p{Cntrl}", // Ký tự điều khiển: [\x00-\x1F\x7F]
"\\p{XDigit}", // Ký tự số hexa: [0-9a-fA-F]
"\\p{Space}" // Ký tự khoảng trắng: [ \t\n\x0B\f\r]
};
// Thực hiện kiểm tra cho mỗi mẫu
for (String patternStr : patterns) {
// Biên dịch mẫu
Pattern pattern = Pattern.compile(patternStr);
Matcher matcher = pattern.matcher(input);
System.out.println("Mẫu: " + patternStr);
// Tìm và in ra các kết quả khớp
while (matcher.find()) {
System.out.println("Khớp: " + matcher.group());
}
System.out.println();
}
}
}
Kết quả của chương trình là:
Mẫu: \p{Lower}
Khớp: e
Khớp: l
Khớp: l
....
Mẫu: \p{Space}
Khớp:
Khớp:
Khớp:
Hy vọng rằng những ví dụ trên đã giúp bạn hiểu rõ hơn về cách sử dụng các lớp ký tự POSIX trong biểu thức chính quy.
5. Các lớp ký tự đơn giản trong Java
Cấu trúc (Construct) | Khớp (Matches) |
---|---|
\p{javaLowerCase} | Tương đương với java.lang.Character.isLowerCase() (ký tự chữ cái viết thường). |
\p{javaUpperCase} | Tương đương với java.lang.Character.isUpperCase() (ký tự chữ cái viết hoa). |
\p{javaWhitespace} | Tương đương với java.lang.Character.isWhitespace() (ký tự khoảng trắng). |
\p{javaMirrored} | Tương đương với java.lang.Character.isMirrored() (ký tự được phản chiếu). |
Dưới đây là ví dụ về cách sử dụng các lớp ký tự đơn giản trong Java với các lớp Pattern và Matcher để kiểm tra các ký tự dựa trên các thuộc tính như chữ cái viết thường, chữ cái viết hoa, ký tự khoảng trắng và ký tự được phản chiếu:
Ví dụ: Example.java
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Example {
public static void main(String[] args) {
String input = "a A \t \u00AA \u212B";
// Các mẫu kiểm tra lớp ký tự
String[] patterns = {
"\\p{javaLowerCase}", // Ký tự chữ cái viết thường
"\\p{javaUpperCase}", // Ký tự chữ cái viết hoa
"\\p{javaWhitespace}", // Ký tự khoảng trắng
"\\p{javaMirrored}" // Ký tự được phản chiếu
};
// Thực hiện kiểm tra cho mỗi mẫu
for (String patternStr : patterns) {
// Biên dịch mẫu
Pattern pattern = Pattern.compile(patternStr);
Matcher matcher = pattern.matcher(input);
System.out.println("Mẫu: " + patternStr);
// Tìm và in ra các kết quả khớp
while (matcher.find()) {
System.out.println("Khớp: " + matcher.group() + " (Vị trí: " + matcher.start() + ")");
}
System.out.println();
}
}
}
Kết quả của chương trình là:
Khớp: a (Vị trí: 0)
Khớp: ª (Vị trí: 6)
Mẫu: \p{javaUpperCase}
Khớp: A (Vị trí: 2)
Khớp: Å (Vị trí: 8)
Mẫu: \p{javaWhitespace}
Khớp: (Vị trí: 1)
Khớp: (Vị trí: 3)
Khớp: (Vị trí: 4)
Khớp: (Vị trí: 5)
Khớp: (Vị trí: 7)
Mẫu: \p{javaMirrored}
Hy vọng rằng những ví dụ trên đã giúp bạn hiểu rõ hơn về cách sử dụng các lớp ký tự đơn giản trong biểu thức chính quy.
6. Các lớp ký tự cho các tập lệnh Unicode, khối, loại và thuộc tính nhị phân
Cấu trúc (Construct) | Khớp (Matches) |
---|---|
\p{IsLatin} | Ký tự thuộc tập lệnh Latin (tập lệnh). |
\p{InGreek} | Ký tự thuộc khối chữ Hy Lạp (khối). |
\p{Lu} | Một chữ cái viết hoa (loại). |
\p{IsAlphabetic} | Ký tự chữ cái (thuộc tính nhị phân). |
\p{Sc} | Một ký hiệu tiền tệ (ký hiệu). |
\P{InGreek} | Bất kỳ ký tự nào ngoại trừ ký tự thuộc khối chữ Hy Lạp (phủ định). |
[ \p{L}&&[^\p{Lu}]] | Bất kỳ ký tự chữ cái nào ngoại trừ chữ cái viết hoa (trừ). |
Dưới đây là ví dụ về cách sử dụng các lớp ký tự liên quan đến Unicode, khối, loại, và thuộc tính nhị phân trong Java để kiểm tra các ký tự thuộc các nhóm khác nhau:
Ví dụ: Example.java
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Example {
public static void main(String[] args) {
String input = "a A € α";
// Các mẫu kiểm tra lớp ký tự Unicode
String[] patterns = {
"\\p{IsLatin}", // Ký tự thuộc tập lệnh Latin
"\\p{InGreek}", // Ký tự thuộc khối chữ Hy Lạp
"\\p{Lu}", // Chữ cái viết hoa
"\\p{IsAlphabetic}", // Ký tự chữ cái
"\\p{Sc}", // Ký hiệu tiền tệ
"\\P{InGreek}", // Bất kỳ ký tự nào ngoại trừ ký tự thuộc khối chữ Hy Lạp
"[\\p{L}&&[^\\p{Lu}]]" // Bất kỳ ký tự chữ cái nào ngoại trừ chữ cái viết hoa
};
// Thực hiện kiểm tra cho mỗi mẫu
for (String patternStr : patterns) {
// Biên dịch mẫu
Pattern pattern = Pattern.compile(patternStr);
Matcher matcher = pattern.matcher(input);
System.out.println("Mẫu: " + patternStr);
// Tìm và in ra các kết quả khớp
while (matcher.find()) {
System.out.println("Khớp: " + matcher.group() + " (Vị trí: " + matcher.start() + ")");
}
System.out.println();
}
}
}
Kết quả của chương trình là:
Khớp: a (Vị trí: 0)
Khớp: A (Vị trí: 2)
..... Mẫu: [\p{L}&&[^\p{Lu}]]
Khớp: a (Vị trí: 0)
Khớp: α (Vị trí: 6)
Hy vọng rằng những ví dụ trên đã giúp bạn hiểu rõ hơn về cách sử dụng các lớp ký tự cho các tập lệnh Unicode, khối, loại và thuộc tính nhị phân trong biểu thức chính quy.
7. Các ký tự kiểm tra ranh giới (Boundary Matchers)
Cấu trúc (Construct) | Khớp (Matches) |
---|---|
^ | Đầu dòng (beginning of a line). |
$ | Cuối dòng (end of a line). |
\b | Ranh giới từ (word boundary). |
\b{g} | Ranh giới của nhóm ký tự Unicode mở rộng (Unicode extended grapheme cluster boundary). |
\B | Không phải ranh giới từ (non-word boundary). |
\A | Đầu của dữ liệu đầu vào (beginning of the input). |
\G | Cuối của lần khớp trước đó (end of the previous match). |
\Z | Cuối của dữ liệu đầu vào, nhưng trước dấu phân cách cuối cùng (nếu có) (end of the input but for the final terminator, if any). |
\z | Cuối của dữ liệu đầu vào (end of the input). |
Dưới đây là ví dụ về cách sử dụng các ký tự kiểm tra ranh giới (boundary matchers) trong một lớp Java để làm việc với các chuỗi văn bản và kiểm tra các điểm ranh giới khác nhau:
Ví dụ: Example.java
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Example {
public static void main(String[] args) {
String input = "Hello world! This is a test. \nNew line.";
// Các mẫu kiểm tra ranh giới
String[] patterns = {
"^", // Đầu dòng
"$", // Cuối dòng
"\\b", // Ranh giới từ
"\\b{g}", // Ranh giới nhóm ký tự Unicode mở rộng
"\\B", // Không phải ranh giới từ
"\\A", // Đầu của dữ liệu đầu vào
"\\G", // Cuối của lần khớp trước đó
"\\Z", // Cuối của dữ liệu đầu vào trước dấu phân cách cuối cùng
"\\z" // Cuối của dữ liệu đầu vào
};
// Thực hiện kiểm tra cho mỗi mẫu
for (String patternStr : patterns) {
// Biên dịch mẫu
Pattern pattern = Pattern.compile(patternStr, Pattern.MULTILINE);
Matcher matcher = pattern.matcher(input);
System.out.println("Mẫu: " + patternStr);
// Tìm và in ra các kết quả khớp
while (matcher.find()) {
System.out.println("Khớp: " + matcher.group() + " (Vị trí: " + matcher.start() + ")");
}
System.out.println();
}
}
}
Kết quả của chương trình là:
Khớp: (Vị trí: 0)
Khớp: (Vị trí: 30)
.....
Mẫu: \z
Khớp: (Vị trí: 39)
Hy vọng rằng những ví dụ trên đã giúp bạn hiểu rõ hơn về cách sử dụng các ký tự kiểm tra ranh giới trong biểu thức chính quy.
8. Ký tự kiểm tra ngắt dòng (Linebreak Matcher)
Cấu trúc (Construct) | Khớp (Matches) |
---|---|
\R | Bất kỳ chuỗi ngắt dòng Unicode nào, tương đương với \u000D\u000A hoặc [\u000A\u000B\u000C\u000D\u0085\u2028\u2029] . |
Dưới đây là ví dụ về cách sử dụng ký tự kiểm tra ngắt dòng (\R) trong một lớp Java để phát hiện và xử lý các chuỗi ngắt dòng Unicode khác nhau:
Ví dụ: Example.java
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Example {
public static void main(String[] args) {
// Chuỗi đầu vào chứa các loại ngắt dòng khác nhau
String input = "Line 1\u0085Line 2\u2028Line 3\u2029Line 4";
// Biên dịch mẫu kiểm tra ngắt dòng
Pattern pattern = Pattern.compile("\\R");
Matcher matcher = pattern.matcher(input);
// In ra các ngắt dòng và vị trí của chúng
System.out.println("Các chuỗi ngắt dòng tìm thấy:");
// Tìm và in ra các kết quả khớp
while (matcher.find()) {
System.out.println("Ngắt dòng tại vị trí: " + matcher.start() + " (Ký tự: " + matcher.group() + ")");
}
}
}
Kết quả của chương trình là:
Ngắt dòng tại vị trí: 6 (Ký tự: )
Ngắt dòng tại vị trí: 13 (Ký tự: )
Ngắt dòng tại vị trí: 20 (Ký tự: )
Hy vọng rằng những ví dụ trên đã giúp bạn hiểu rõ hơn về cách sử dụng các ký tự kiểm tra ngắt dòng trong biểu thức chính quy.
9. Ký tự kiểm tra nhóm ký tự Unicode mở rộng (Unicode Extended Grapheme Matcher)
Cấu trúc (Construct) | Khớp (Matches) |
---|---|
\X | Bất kỳ nhóm ký tự Unicode mở rộng nào (Any Unicode extended grapheme cluster). |
Dưới đây là một ví dụ Java sử dụng lớp Pattern và Matcher để kiểm tra các nhóm ký tự Unicode mở rộng (Unicode extended grapheme clusters) với ký tự \X:
Ví dụ: Example.java
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Example {
public static void main(String[] args) {
// Chuỗi đầu vào chứa các nhóm ký tự Unicode mở rộng
String input = "a̐áâǎäåą"; // Các ký tự Unicode mở rộng bao gồm các dấu phụ
// Biên dịch mẫu kiểm tra nhóm ký tự Unicode mở rộng
Pattern pattern = Pattern.compile("\\X");
Matcher matcher = pattern.matcher(input);
// In ra các nhóm ký tự Unicode mở rộng và vị trí của chúng
System.out.println("Các nhóm ký tự Unicode mở rộng tìm thấy:");
// Tìm và in ra các kết quả khớp
while (matcher.find()) {
System.out.println("Nhóm ký tự tại vị trí: " + matcher.start() + " - " + matcher.end() + " (Ký tự: " + matcher.group() + ")");
}
}
}
Kết quả của chương trình là:
Nhóm ký tự tại vị trí: 0 - 2 (Ký tự: a̐)
Nhóm ký tự tại vị trí: 2 - 4 (Ký tự: á)
Nhóm ký tự tại vị trí: 4 - 6 (Ký tự: â)
Nhóm ký tự tại vị trí: 6 - 8 (Ký tự: ǎ)
Nhóm ký tự tại vị trí: 8 - 10 (Ký tự: ä)
Nhóm ký tự tại vị trí: 10 - 12 (Ký tự: å)
Nhóm ký tự tại vị trí: 12 - 14 (Ký tự: ą)
Hy vọng rằng những ví dụ trên đã giúp bạn hiểu rõ hơn về cách sử dụng các ký tự kiểm tra ngắt dòng trong biểu thức chính quy.
10. Ký tự định lượng tham lam (Greedy Quantifiers)
Cấu trúc (Construct) | Khớp (Matches) |
---|---|
X? | Ký tự X , xuất hiện một lần hoặc không có (once or not at all). |
X* | Ký tự X , xuất hiện từ 0 lần trở lên (zero or more times). |
X+ | Ký tự X , xuất hiện ít nhất một lần (one or more times). |
X{n} | Ký tự X , xuất hiện chính xác n lần (exactly n times). |
X{n,} | Ký tự X , xuất hiện ít nhất n lần (at least n times). |
X{n, m} | Ký tự X , xuất hiện ít nhất n lần và không quá m lần (at least n but not more than m times). |
Dưới đây là một ví dụ Java sử dụng lớp Pattern và Matcher để minh họa các ký tự định lượng tham lam (greedy quantifiers):
Ví dụ: Example.java
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Example {
public static void main(String[] args) {
// Chuỗi đầu vào để kiểm tra các ký tự định lượng tham lam
String input = "aaabaaaabaaa";
// Ví dụ với các ký tự định lượng tham lam khác nhau
// X? - X xuất hiện một lần hoặc không có
Pattern pattern1 = Pattern.compile("a?"); // X? với X là 'a'
Matcher matcher1 = pattern1.matcher(input);
System.out.println("Kết quả cho 'a?':");
while (matcher1.find()) {
System.out.println("Vị trí: " + matcher1.start() + " - " + matcher1.end() + " (Ký tự: " + matcher1.group() + ")");
}
// X* - X xuất hiện từ 0 lần trở lên
Pattern pattern2 = Pattern.compile("a*"); // X* với X là 'a'
Matcher matcher2 = pattern2.matcher(input);
System.out.println("\nKết quả cho 'a*':");
while (matcher2.find()) {
System.out.println("Vị trí: " + matcher2.start() + " - " + matcher2.end() + " (Ký tự: " + matcher2.group() + ")");
}
// X+ - X xuất hiện ít nhất một lần
Pattern pattern3 = Pattern.compile("a+"); // X+ với X là 'a'
Matcher matcher3 = pattern3.matcher(input);
System.out.println("\nKết quả cho 'a+':");
while (matcher3.find()) {
System.out.println("Vị trí: " + matcher3.start() + " - " + matcher3.end() + " (Ký tự: " + matcher3.group() + ")");
}
// X{n} - X xuất hiện chính xác n lần
Pattern pattern4 = Pattern.compile("a{3}"); // X{3} với X là 'a'
Matcher matcher4 = pattern4.matcher(input);
System.out.println("\nKết quả cho 'a{3}':");
while (matcher4.find()) {
System.out.println("Vị trí: " + matcher4.start() + " - " + matcher4.end() + " (Ký tự: " + matcher4.group() + ")");
}
// X{n,} - X xuất hiện ít nhất n lần
Pattern pattern5 = Pattern.compile("a{2,}"); // X{2,} với X là 'a'
Matcher matcher5 = pattern5.matcher(input);
System.out.println("\nKết quả cho 'a{2,}':");
while (matcher5.find()) {
System.out.println("Vị trí: " + matcher5.start() + " - " + matcher5.end() + " (Ký tự: " + matcher5.group() + ")");
}
// X{n,m} - X xuất hiện ít nhất n lần và không quá m lần
Pattern pattern6 = Pattern.compile("a{2,4}"); // X{2,4} với X là 'a'
Matcher matcher6 = pattern6.matcher(input);
System.out.println("\nKết quả cho 'a{2,4}':");
while (matcher6.find()) {
System.out.println("Vị trí: " + matcher6.start() + " - " + matcher6.end() + " (Ký tự: " + matcher6.group() + ")");
}
}
}
Kết quả của chương trình là:
Kết quả cho 'a?':
Vị trí: 0 - 1 (Ký tự: a)
Vị trí: 1 - 2 (Ký tự: a)
Vị trí: 2 - 3 (Ký tự: a)
Vị trí: 3 - 3 (Ký tự: )
...... Kết quả cho 'a{2, 4}':
Vị trí: 0 - 3 (Ký tự: aaa)
Vị trí: 4 - 8 (Ký tự: aaaa)
Vị trí: 9 - 12 (Ký tự: aaa)
Hy vọng rằng những ví dụ trên đã giúp bạn hiểu rõ hơn về cách sử dụng các ký tự định lượng tham lam trong biểu thức chính quy.
11. Ký tự định lượng ngần ngại (Reluctant Quantifiers)
Cấu trúc (Construct) | Khớp (Matches) |
---|---|
X?? | Ký tự X, xuất hiện một lần hoặc không có (once or not at all). |
X*? | Ký tự X, xuất hiện từ 0 lần trở lên (zero or more times). |
X+? | Ký tự X, xuất hiện ít nhất một lần (one or more times). |
X{n}? | Ký tự X, xuất hiện chính xác n lần (exactly n times). |
X{n,}? | Ký tự X, xuất hiện ít nhất n lần (at least n times). |
X{n,m}? | Ký tự X, xuất hiện ít nhất n lần và không quá m lần (at least n but not more than m times). |
Dưới đây là ví dụ về các ký tự định lượng ngần ngại (reluctant quantifiers) trong một lớp Java. Các ký tự định lượng ngần ngại cố gắng khớp ít nhất có thể và sau đó tiếp tục tìm kiếm các kết quả khác nếu cần.
Ví dụ: Example.java
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Example {
public static void main(String[] args) {
// Chuỗi đầu vào để kiểm tra các ký tự định lượng ngần ngại
String input = "aaabaaaabaaa";
// Ví dụ với các ký tự định lượng ngần ngại khác nhau
// X?? - X xuất hiện một lần hoặc không có
Pattern pattern1 = Pattern.compile("a??"); // X?? với X là 'a'
Matcher matcher1 = pattern1.matcher(input);
System.out.println("Kết quả cho 'a??':");
while (matcher1.find()) {
System.out.println("Vị trí: " + matcher1.start() + " - " + matcher1.end() + " (Ký tự: " + matcher1.group() + ")");
}
// X*? - X xuất hiện từ 0 lần trở lên
Pattern pattern2 = Pattern.compile("a*?"); // X*? với X là 'a'
Matcher matcher2 = pattern2.matcher(input);
System.out.println("\nKết quả cho 'a*?':");
while (matcher2.find()) {
System.out.println("Vị trí: " + matcher2.start() + " - " + matcher2.end() + " (Ký tự: " + matcher2.group() + ")");
}
// X+? - X xuất hiện ít nhất một lần
Pattern pattern3 = Pattern.compile("a+?"); // X+? với X là 'a'
Matcher matcher3 = pattern3.matcher(input);
System.out.println("\nKết quả cho 'a+?':");
while (matcher3.find()) {
System.out.println("Vị trí: " + matcher3.start() + " - " + matcher3.end() + " (Ký tự: " + matcher3.group() + ")");
}
// X{n}? - X xuất hiện chính xác n lần
Pattern pattern4 = Pattern.compile("a{3}?"); // X{3}? với X là 'a'
Matcher matcher4 = pattern4.matcher(input);
System.out.println("\nKết quả cho 'a{3}?':");
while (matcher4.find()) {
System.out.println("Vị trí: " + matcher4.start() + " - " + matcher4.end() + " (Ký tự: " + matcher4.group() + ")");
}
// X{n,}? - X xuất hiện ít nhất n lần
Pattern pattern5 = Pattern.compile("a{2,}?"); // X{2,}? với X là 'a'
Matcher matcher5 = pattern5.matcher(input);
System.out.println("\nKết quả cho 'a{2,}?':");
while (matcher5.find()) {
System.out.println("Vị trí: " + matcher5.start() + " - " + matcher5.end() + " (Ký tự: " + matcher5.group() + ")");
}
// X{n,m}? - X xuất hiện ít nhất n lần và không quá m lần
Pattern pattern6 = Pattern.compile("a{2,4}?"); // X{2,4}? với X là 'a'
Matcher matcher6 = pattern6.matcher(input);
System.out.println("\nKết quả cho 'a{2,4}?':");
while (matcher6.find()) {
System.out.println("Vị trí: " + matcher6.start() + " - " + matcher6.end() + " (Ký tự: " + matcher6.group() + ")");
}
}
}
Kết quả của chương trình là:
Vị trí: 0 - 0 (Ký tự: )
Vị trí: 1 - 1 (Ký tự: )
...
Kết quả cho 'a{2,4}?':
Vị trí: 0 - 2 (Ký tự: aa)
Vị trí: 4 - 6 (Ký tự: aa)
Vị trí: 6 - 8 (Ký tự: aa)
Vị trí: 9 - 11 (Ký tự: aa)
Hy vọng rằng những ví dụ trên đã giúp bạn hiểu rõ hơn về cách sử dụng các ký tự định lượng ngần ngại trong biểu thức chính quy.
12. Ký tự định lượng chiếm hữu (Possessive Quantifiers)
Cấu trúc (Construct) | Khớp (Matches) |
---|---|
X?+ | Ký tự X, xuất hiện một lần hoặc không có (once or not at all). |
X*+ | Ký tự X, xuất hiện từ 0 lần trở lên (zero or more times). |
X++ | Ký tự X, xuất hiện ít nhất một lần (one or more times). |
X{n}+ | Ký tự X, xuất hiện chính xác n lần (exactly n times). |
X{n,}+ | Ký tự X, xuất hiện ít nhất n lần (at least n times). |
X{n,m}+ | Ký tự X, xuất hiện ít nhất n lần và không quá m lần (at least n but not more than m times). |
Dưới đây là ví dụ về các ký tự định lượng chiếm hữu (possessive quantifiers) trong một lớp Java. Các ký tự định lượng chiếm hữu không cho phép các phần của chuỗi được quay lại và thử các kết quả khác sau khi đã khớp. Chúng "chiếm hữu" hoàn toàn các ký tự mà chúng khớp với.
Ví dụ: Example.java
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Example {
public static void main(String[] args) {
// Chuỗi đầu vào để kiểm tra các ký tự định lượng chiếm hữu
String input = "aaabaaaabaaa";
// Ví dụ với các ký tự định lượng chiếm hữu khác nhau
// X?+ - X xuất hiện một lần hoặc không có
Pattern pattern1 = Pattern.compile("a?+"); // X?+ với X là 'a'
Matcher matcher1 = pattern1.matcher(input);
System.out.println("Kết quả cho 'a?+':");
while (matcher1.find()) {
System.out.println("Vị trí: " + matcher1.start() + " - " + matcher1.end() + " (Ký tự: " + matcher1.group() + ")");
}
// X*+ - X xuất hiện từ 0 lần trở lên
Pattern pattern2 = Pattern.compile("a*+"); // X*+ với X là 'a'
Matcher matcher2 = pattern2.matcher(input);
System.out.println("\nKết quả cho 'a*+':");
while (matcher2.find()) {
System.out.println("Vị trí: " + matcher2.start() + " - " + matcher2.end() + " (Ký tự: " + matcher2.group() + ")");
}
// X++ - X xuất hiện ít nhất một lần
Pattern pattern3 = Pattern.compile("a++"); // X++ với X là 'a'
Matcher matcher3 = pattern3.matcher(input);
System.out.println("\nKết quả cho 'a++':");
while (matcher3.find()) {
System.out.println("Vị trí: " + matcher3.start() + " - " + matcher3.end() + " (Ký tự: " + matcher3.group() + ")");
}
// X{n}+ - X xuất hiện chính xác n lần
Pattern pattern4 = Pattern.compile("a{3}+"); // X{3}+ với X là 'a'
Matcher matcher4 = pattern4.matcher(input);
System.out.println("\nKết quả cho 'a{3}+':");
while (matcher4.find()) {
System.out.println("Vị trí: " + matcher4.start() + " - " + matcher4.end() + " (Ký tự: " + matcher4.group() + ")");
}
// X{n,}+ - X xuất hiện ít nhất n lần
Pattern pattern5 = Pattern.compile("a{2,}+"); // X{2,}+ với X là 'a'
Matcher matcher5 = pattern5.matcher(input);
System.out.println("\nKết quả cho 'a{2,}+:");
while (matcher5.find()) {
System.out.println("Vị trí: " + matcher5.start() + " - " + matcher5.end() + " (Ký tự: " + matcher5.group() + ")");
}
// X{n,m}+ - X xuất hiện ít nhất n lần và không quá m lần
Pattern pattern6 = Pattern.compile("a{2,4}+"); // X{2,4}+ với X là 'a'
Matcher matcher6 = pattern6.matcher(input);
System.out.println("\nKết quả cho 'a{2,4}+':");
while (matcher6.find()) {
System.out.println("Vị trí: " + matcher6.start() + " - " + matcher6.end() + " (Ký tự: " + matcher6.group() + ")");
}
}
}
Kết quả của chương trình là:
Vị trí: 0 - 0 (Ký tự: )
...
Kết quả cho 'a{2,4}+':
Vị trí: 0 - 3 (Ký tự: aaa)
Vị trí: 4 - 8 (Ký tự: aaaa)
Vị trí: 9 - 12 (Ký tự: aaa)
Hy vọng rằng những ví dụ trên đã giúp bạn hiểu rõ hơn về cách sử dụng các ký tự định lượng chiếm hữu trong biểu thức chính quy.
13. Toán tử Logic
Cấu trúc (Construct) | Khớp (Matches) |
---|---|
XY | Ký tự X theo sau ký tự Y (X followed by Y). |
X|Y | Hoặc X hoặc Y (Either X or Y). |
(X) | Ký tự X, như là một nhóm bắt giữ (capturing group). |
Dưới đây là ví dụ về các toán tử logic trong một lớp Java sử dụng biểu thức chính quy:
Ví dụ: Example.java
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Example {
public static void main(String[] args) {
// Chuỗi đầu vào để kiểm tra các toán tử logic
String input = "apple banana cherry";
// Ví dụ với các toán tử logic khác nhau
// XY - Ký tự X theo sau ký tự Y (X followed by Y)
Pattern pattern1 = Pattern.compile("apple banana"); // 'apple' theo sau 'banana'
Matcher matcher1 = pattern1.matcher(input);
System.out.println("Kết quả cho 'apple banana':");
while (matcher1.find()) {
System.out.println("Vị trí: " + matcher1.start() + " - " + matcher1.end() + " (Ký tự: " + matcher1.group() + ")");
}
// X|Y - Hoặc X hoặc Y (Either X or Y)
Pattern pattern2 = Pattern.compile("apple|banana"); // 'apple' hoặc 'banana'
Matcher matcher2 = pattern2.matcher(input);
System.out.println("\nKết quả cho 'apple|banana':");
while (matcher2.find()) {
System.out.println("Vị trí: " + matcher2.start() + " - " + matcher2.end() + " (Ký tự: " + matcher2.group() + ")");
}
// (X) - Ký tự X, như là một nhóm bắt giữ (capturing group)
Pattern pattern3 = Pattern.compile("(apple) (banana)"); // 'apple' và 'banana' là các nhóm bắt giữ
Matcher matcher3 = pattern3.matcher(input);
System.out.println("\nKết quả cho '(apple) (banana)':");
while (matcher3.find()) {
System.out.println("Vị trí: " + matcher3.start() + " - " + matcher3.end());
System.out.println("Nhóm 1: " + matcher3.group(1)); // 'apple'
System.out.println("Nhóm 2: " + matcher3.group(2)); // 'banana'
}
}
}
Kết quả của chương trình là:
Kết quả cho 'apple banana': Vị trí: 0 - 12 (Ký tự: apple banana)
Kết quả cho 'apple|banana':
Vị trí: 0 - 5 (Ký tự: apple)
Vị trí: 6 - 12 (Ký tự: banana)
Kết quả cho '(apple) (banana)':
Vị trí: 0 - 12
Nhóm 1: apple
Nhóm 2: banana
Hy vọng rằng những ví dụ trên đã giúp bạn hiểu rõ hơn về cách sử dụng các ký tự Toán tử Logic trong biểu thức chính quy.
14. Tham chiếu lại
Cấu trúc (Construct) | Khớp (Matches) |
---|---|
\n | Giá trị mà nhóm bắt giữ thứ n khớp với (Whatever the nth capturing group matched). |
\k<name> | Giá trị mà nhóm bắt giữ tên "name" khớp với (Whatever the named-capturing group "name" matched). |
Dưới đây là ví dụ về cách sử dụng các tham chiếu lại trong một lớp Java với biểu thức chính quy, bao gồm việc sử dụng nhóm bắt giữ thứ n (\n) và nhóm bắt giữ tên (\k<name>).
Ví dụ: Example.java
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Example {
public static void main(String[] args) {
// Chuỗi đầu vào để kiểm tra các tham chiếu lại
String input = "apple apple orange orange";
// Ví dụ với nhóm bắt giữ thứ n
// Mẫu tìm kiếm '(\w+) \\1' tìm một từ, theo sau bởi chính từ đó
Pattern pattern1 = Pattern.compile("(\\w+) \\1");
Matcher matcher1 = pattern1.matcher(input);
System.out.println("Kết quả cho '(\\w+) \\1':");
while (matcher1.find()) {
System.out.println("Vị trí: " + matcher1.start() + " - " + matcher1.end());
System.out.println("Nhóm 1: " + matcher1.group(1)); // Từ lặp lại
}
// Ví dụ với nhóm bắt giữ tên
// Mẫu tìm kiếm '(?<fruit>\\w+) \\k<fruit>' tìm một từ, theo sau bởi chính từ đó với tên nhóm
Pattern pattern2 = Pattern.compile("(?<fruit>\\w+) \\k<fruit>");
Matcher matcher2 = pattern2.matcher(input);
System.out.println("\nKết quả cho '(?<fruit>\\w+) \\k<fruit>':");
while (matcher2.find()) {
System.out.println("Vị trí: " + matcher2.start() + " - " + matcher2.end());
System.out.println("Nhóm 'fruit': " + matcher2.group("fruit")); // Từ lặp lại với tên nhóm
}
}
}
Kết quả của chương trình là:
Vị trí: 0 - 11
Nhóm 1: apple
Vị trí: 12 - 25
Nhóm 1: orange
Kết quả cho '(?<fruit>\w+) \k<fruit>':
Vị trí: 0 - 11
Nhóm 'fruit': apple
Vị trí: 12 - 25
Nhóm 'fruit': orange
Hy vọng rằng những ví dụ trên đã giúp bạn hiểu rõ hơn về cách sử dụng các ký tự tham chiếu lại trong biểu thức chính quy.
15. Trích dẫn (Quotation)
Cấu trúc (Construct) | Khớp (Matches) |
---|---|
\ | Không có tác dụng gì nhưng trích dẫn ký tự sau đó (Quotes the following character). |
\Q | Không có tác dụng gì nhưng trích dẫn tất cả các ký tự cho đến khi gặp \E (Quotes all characters until \E ). |
\E | Không có tác dụng gì nhưng kết thúc trích dẫn bắt đầu bằng \Q (Ends quoting started by \Q ). |
Dưới đây là ví dụ về cách sử dụng các ký tự trích dẫn (\, \Q, \E) trong biểu thức chính quy bằng Java. Ví dụ này cho thấy cách sử dụng ký tự trích dẫn để khớp các ký tự đặc biệt hoặc chuỗi chứa các ký tự đặc biệt mà không cần phải thoát chúng một cách riêng lẻ.
Ví dụ: Example.java
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Example {
public static void main(String[] args) {
// Chuỗi đầu vào để kiểm tra trích dẫn
String input1 = "Hello, $pecial* characters here!";
String input2 = "Special characters: $pecial*";
// Ví dụ với trích dẫn ký tự đơn giản
// Mẫu tìm kiếm 'Hello, \$pecial\* characters here!' với ký tự '$' và '*' được trích dẫn
Pattern pattern1 = Pattern.compile("Hello, \\$pecial\\* characters here!");
Matcher matcher1 = pattern1.matcher(input1);
System.out.println("Kết quả cho 'Hello, \\$pecial\\* characters here!':");
while (matcher1.find()) {
System.out.println("Vị trí: " + matcher1.start() + " - " + matcher1.end());
System.out.println("Khớp: " + matcher1.group());
}
// Ví dụ với trích dẫn toàn bộ chuỗi
// Mẫu tìm kiếm 'Hello, \Q$pecial* characters\E here!' với ký tự '$' và '*' được trích dẫn
Pattern pattern2 = Pattern.compile("Hello, \\Q$pecial* characters\\E here!");
Matcher matcher2 = pattern2.matcher(input2);
System.out.println("\nKết quả cho 'Hello, \\Q$pecial* characters\\E here!':");
while (matcher2.find()) {
System.out.println("Vị trí: " + matcher2.start() + " - " + matcher2.end());
System.out.println("Khớp: " + matcher2.group());
}
}
}
Kết quả của chương trình là:
Vị trí: 0 - 32
Khớp: Hello, $pecial* characters here!
Kết quả cho 'Hello, \Q$pecial* characters\E here!':
Hy vọng rằng những ví dụ trên đã giúp bạn hiểu rõ hơn về cách sử dụng các ký tự trích dẫn trong biểu thức chính quy.
16. Các cấu trúc đặc biệt
Cấu trúc (Construct) | Khớp (Matches) |
---|---|
(?<name>X) | Ký tự X , như là một nhóm bắt giữ tên (named-capturing group) với tên là "name". |
(?:X) | Ký tự X , như là một nhóm không bắt giữ (non-capturing group). |
(?idmsuxU-idmsuxU) | Không có tác dụng gì, nhưng bật hoặc tắt các cờ (flags) so khớp i d m s u x U (match flags). |
(?idmsuxU-idmsuxU:X) | Ký tự X , như là một nhóm không bắt giữ với các cờ (flags) i d m s u x U bật hoặc tắt. |
(?=X) | Ký tự X , qua kiểm tra dương không rộng (zero-width positive lookahead). |
(?!X) | Ký tự X , qua kiểm tra âm không rộng (zero-width negative lookahead). |
(?<=X) | Ký tự X , qua kiểm tra dương không rộng từ phía sau (zero-width positive lookbehind). |
(?<!X) | Ký tự X , qua kiểm tra âm không rộng từ phía sau (zero-width negative lookbehind). |
(?>X) | Ký tự X , như là một nhóm độc lập không bắt giữ (independent, non-capturing group). |
Dưới đây là ví dụ về cách sử dụng các cấu trúc đặc biệt trong biểu thức chính quy trong Java. Ví dụ này sẽ trình bày cách sử dụng các nhóm bắt giữ tên, nhóm không bắt giữ, kiểm tra dương và âm không rộng, cũng như các nhóm độc lập không bắt giữ.
Ví dụ: Example.java
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Example {
public static void main(String[] args) {
String input = "The price is $100 and the discount is $10.";
// Nhóm bắt giữ tên
Pattern namedCapturePattern = Pattern.compile("The price is (?<price>\\$\\d+) and the discount is (?<discount>\\$\\d+).");
Matcher namedCaptureMatcher = namedCapturePattern.matcher(input);
System.out.println("Nhóm bắt giữ tên:");
while (namedCaptureMatcher.find()) {
System.out.println("Giá: " + namedCaptureMatcher.group("price"));
System.out.println("Giảm giá: " + namedCaptureMatcher.group("discount"));
}
// Nhóm không bắt giữ
Pattern nonCapturingGroupPattern = Pattern.compile("The price is (?:\\$\\d+) and the discount is (?:\\$\\d+).");
Matcher nonCapturingGroupMatcher = nonCapturingGroupPattern.matcher(input);
System.out.println("\nNhóm không bắt giữ:");
while (nonCapturingGroupMatcher.find()) {
System.out.println("Toàn bộ khớp: " + nonCapturingGroupMatcher.group());
}
// Kiểm tra dương không rộng
Pattern positiveLookaheadPattern = Pattern.compile("(?=\\$\\d+)");
Matcher positiveLookaheadMatcher = positiveLookaheadPattern.matcher(input);
System.out.println("\nKiểm tra dương không rộng:");
while (positiveLookaheadMatcher.find()) {
System.out.println("Khớp tại vị trí: " + positiveLookaheadMatcher.start());
}
// Kiểm tra âm không rộng
Pattern negativeLookaheadPattern = Pattern.compile("(?!\\d{3})\\d+");
Matcher negativeLookaheadMatcher = negativeLookaheadPattern.matcher("Price is 1000");
System.out.println("\nKiểm tra âm không rộng:");
while (negativeLookaheadMatcher.find()) {
System.out.println("Khớp: " + negativeLookaheadMatcher.group());
}
// Kiểm tra dương không rộng từ phía sau
Pattern positiveLookbehindPattern = Pattern.compile("(?<=\\$)\\d+");
Matcher positiveLookbehindMatcher = positiveLookbehindPattern.matcher(input);
System.out.println("\nKiểm tra dương không rộng từ phía sau:");
while (positiveLookbehindMatcher.find()) {
System.out.println("Giá trị sau ký tự '$': " + positiveLookbehindMatcher.group());
}
// Kiểm tra âm không rộng từ phía sau
Pattern negativeLookbehindPattern = Pattern.compile("(?<!\\$)\\d+");
Matcher negativeLookbehindMatcher = negativeLookbehindPattern.matcher("Discount is 10, no $100 here.");
System.out.println("\nKiểm tra âm không rộng từ phía sau:");
while (negativeLookbehindMatcher.find()) {
System.out.println("Giảm giá không theo sau ký tự '$': " + negativeLookbehindMatcher.group());
}
// Nhóm độc lập không bắt giữ
Pattern independentGroupPattern = Pattern.compile("(?>\\d+)");
Matcher independentGroupMatcher = independentGroupPattern.matcher("123 456");
System.out.println("\nNhóm độc lập không bắt giữ:");
while (independentGroupMatcher.find()) {
System.out.println("Khớp: " + independentGroupMatcher.group());
}
}
}
Kết quả của chương trình là:
Giá: $100
Giảm giá: $10
...
Nhóm độc lập không bắt giữ:
Khớp: 123
Khớp: 456
Hy vọng rằng những ví dụ trên đã giúp bạn hiểu rõ hơn về cách sử dụng các ký tự cấu trúc đặc biệt trong biểu thức chính quy.
Trong phần này, chúng ta đã khám phá các cấu trúc đặc biệt trong biểu thức chính quy, bao gồm nhóm bắt giữ tên, nhóm không bắt giữ, kiểm tra dương và âm không rộng, cũng như các nhóm độc lập không bắt giữ. Việc hiểu và áp dụng các cấu trúc này giúp nâng cao khả năng viết các biểu thức chính quy mạnh mẽ và linh hoạt, cho phép bạn thực hiện các thao tác phức tạp và tinh vi trên chuỗi văn bản. Từ việc trích xuất thông tin đến kiểm tra mẫu, các cấu trúc này mở rộng khả năng xử lý văn bản của bạn, giúp giải quyết các bài toán thực tế một cách hiệu quả hơn.