Java: Các phương thức của lớp Pattern
Cho đến thời điểm này ta chỉ sử dụng test harness để tạo các đối tượng Pattern ở dạng cơ bản nhất của chúng. Bài viết này khám phá các kỹ thuật nâng cao như tạo mẫu với cờ và sử dụng biểu thức cờ được nhúng. Bài viết cũng khám phá một số phương pháp hữu ích bổ sung mà chúng ta chưa từng nói đến.
Tạo mẫu bằng cờ
Lớp Pattern định nghĩa một phương thức compile thay thế trong đó chấp nhận một tập hợp các cờ ảnh hưởng đến cách so khớp mẫu. Tham số cờ là một mặt nạ bit có thể bao gồm bất kỳ trường tĩnh public nào sau đây:
Pattern.CANON_EQ
Khi cờ này được chỉ định, hai ký tự sẽ được coi là khớp nếu và chỉ nếu, các phân tích hợp quy đầy đủ của chúng khớp nhau. Ví dụ: biểu thức "a\u030A" sẽ khớp với chuỗi "\u00E5" khi cờ này được chỉ định. Theo mặc định, đối sánh không tính đến tính tương đương chính tắc. Chỉ định cờ này có thể gây ra hình phạt về hiệu suất.Pattern.CASE_INSENSITIVE
Cho phép đối sánh không phân biệt chữ hoa chữ thường. Theo mặc định, đối sánh không phân biệt chữ hoa chữ thường giả định rằng chỉ các ký tự trong bộ mã US-ASCII mới được so khớp. Có thể bật đối sánh phân biệt chữ hoa chữ thường nhận biết Unicode bằng cách chỉ định cờ UNICODE_CASE cùng với cờ này. Đối sánh không phân biệt chữ hoa chữ thường cũng có thể được bật thông qua biểu thức cờ nhúng (?i). Việc chỉ định cờ này có thể áp dụng một hình phạt nhẹ về hiệu suất.Pattern.COMMENTS
Cho phép khoảng trắng và comment trong mẫu. Trong chế độ này, khoảng trắng bị bỏ qua và các nhận xét được nhúng bắt đầu bằng # sẽ bị bỏ qua cho đến cuối dòng. Chế độ nhận xét cũng có thể được bật thông qua biểu thức cờ nhúng (?x).Pattern.DOTALL
Trong chế độ dotall, biểu thức . khớp với bất kỳ ký tự nào, kể cả ký tự kết thúc dòng. Theo mặc định, biểu thức này không khớp với các dấu cuối dòng. Chế độ dotall cũng có thể được kích hoạt thông qua biểu thức cờ nhúng (?s). (s là cách ghi nhớ cho chế độ "một dòng").Pattern.LITERAL
Cho phép phân tích cú pháp theo nghĩa đen của mẫu. Khi cờ này được chỉ định thì chuỗi đầu vào chỉ định mẫu được coi như một chuỗi các ký tự chữ. Các siêu ký tự hoặc chuỗi thoát trong chuỗi đầu vào sẽ không có ý nghĩa đặc biệt. Các cờ CASE_INSENSITIVE và UNICODE_CASE giữ nguyên tác động của chúng đối với việc đối sánh khi được sử dụng cùng với cờ này. Các cờ khác trở nên thừa. Không có ký tự cờ nào được nhúng để cho phép phân tích cú pháp theo nghĩa đen.Pattern.MULTILINE
Bật chế độ nhiều dòng. Trong chế độ nhiều dòng, các biểu thức ^ và $ so khớp ngay sau hoặc ngay trước, tương ứng với một dấu chấm cuối dòng hoặc cuối chuỗi đầu vào. Theo mặc định, các biểu thức này chỉ khớp ở phần đầu và phần cuối của toàn bộ chuỗi đầu vào. Chế độ đa dòng cũng có thể được bật thông qua biểu thức cờ nhúng (?m).Pattern.UNICODE_CASE
Cho phép gấp chữ viết hoa nhận biết Unicode. Khi cờ này được chỉ định thì đối sánh không phân biệt chữ hoa chữ thường, khi được cờ CASE_INSENSITIVE bật thì sẽ được thực hiện theo cách nhất quán với chuẩn Unicode. Theo mặc định, đối sánh không phân biệt chữ hoa chữ thường giả định rằng chỉ các ký tự trong bộ mã US-ASCII mới được so khớp. Tính năng gập chữ hoa chữ thường nhận biết Unicode cũng có thể được bật thông qua biểu thức cờ nhúng (?u). Chỉ định cờ này có thể áp dụng hình phạt về hiệu suất.Pattern.UNIX_LINES
Bật chế độ dòng UNIX. Trong chế độ này, chỉ ký tự xuống dòng '\ n' được nhận dạng trong hành vi của ., ^ và $. Chế độ dòng UNIX cũng có thể được kích hoạt thông qua biểu thức cờ nhúng (?d).
Trong các bước sau, ta sẽ sửa đổi bộ test harness để tạo một mẫu với đối sánh không phân biệt chữ hoa chữ thường.
Trước tiên ta sẽ sửa đổi mã lệnh để gọi phiên bản của compile
thay thế:
Pattern pattern = Pattern.compile(console.readLine("%nEnter your regex: "), Pattern.CASE_INSENSITIVE);
Sau đó biên dịch và chạy test harness để lấy kết quả như sau:
Enter your regex: dog Enter input string to search: DoGDOg I found the text "DoG" starting at index 0 and ending at index 3. I found the text "DOg" starting at index 3 and ending at index 6.
Như bạn có thể thấy, chuỗi theo nghĩa đen "dog" khớp với cả hai lần xuất hiện, bất kể chữ hoa và chữ thường. Để biên dịch một mẫu có nhiều cờ, hãy tách các cờ được đưa vào bằng toán tử OR bitwise "|". Để tường minh thì đoạn mã sau lấy mẫu mã hóa cứng biểu thức chính quy thay vì đọc nó từ Console
:
pattern = Pattern.compile("[az]$", Pattern.MULTILINE | Pattern.UNIX_LINES);
Bạn cũng có thể xác định một biến kiểu int
thay thế:
final int flags = Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE; Pattern pattern = Pattern.compile("aa", flags);
Các biểu thức cờ được nhúng
Cũng có thể bật các cờ khác nhau bằng cách sử dụng các biểu thức cờ được nhúng. Biểu thức cờ được nhúng là một thay thế cho phiên bản hai đối số của compile
và được chỉ định trong chính biểu thức chính quy. Ví dụ sau sử dụng test harness với biểu thức cờ nhúng (?i) để kích hoạt đối sánh không phân biệt chữ hoa chữ thường.
Enter your regex: (?i)foo Enter input string to search: FOOfooFoOfoO I found the text "FOO" starting at index 0 and ending at index 3. I found the text "foo" starting at index 3 and ending at index 6. I found the text "FoO" starting at index 6 and ending at index 9. I found the text "foO" starting at index 9 and ending at index 12
Một lần nữa, tất cả các đối sánh đều thành công đối với bất kể trường hợp nào.
Các biểu thức cờ nhúng tương ứng với các trường có thể truy cập công khai của Pattern được trình bày trong bảng sau:
Hằng | Biểu thức cờ nhúng tương đương |
---|---|
Pattern.CANON_EQ |
None |
Pattern.CASE_INSENSITIVE |
(?i) |
Pattern.COMMENTS |
(?x) |
Pattern.MULTILINE |
(?m) |
Pattern.DOTALL |
(?s) |
Pattern.LITERAL |
None |
Pattern.UNICODE_CASE |
(?u) |
Pattern.UNIX_LINES |
(?d) |
Sử dụng phương thức matches(String,CharSequence)
Lớp Pattern định nghĩa một phương thức so khớp thuận tiện cho phép bạn nhanh chóng kiểm tra xem một mẫu có xuất hiện trong một chuỗi đầu vào nhất định hay không. Như với tất cả các phương thức tĩnh công khai, bạn nên gọi các kết quả phù hợp theo tên lớp của nó, chẳng hạn như Pattern.matches("\\d","1");
. Trong ví dụ này, phương thức trả về true vì chữ số "1" khớp với biểu thức chính quy \d.
Sử dụng phương thức split(String)
Phương thức split
là một công cụ tốt để thu thập văn bản nằm ở hai bên của mẫu đã được khớp. Như được thể hiện ở ví dụ bên dưới trong lớp SplitDemo, phương thức split có thể trích xuất các từ "one two three four five" từ chuỗi "one:two:three:four:five":
package solutions; import java.util.regex.Pattern; public class SplitDemo { private static final String REGEX = ":"; private static final String INPUT = "one:two:three:four:five"; public static void main(String[] args) { Pattern p = Pattern.compile(REGEX); String[] items = p.split(INPUT); for (String s : items) { System.out.println(s); } } }
Kết quả:
one
two
three
four
five
Để đơn giản ta so khớp một chuỗi ký tự dấu hai chấm (:) thay vì một biểu thức chính quy phức tạp. Vì ta vẫn đang sử dụng các đối tượng Pattern và Matcher, nên ta có thể sử dụng phương thức split() để lấy văn bản nằm ở hai bên của bất kỳ biểu thức chính quy nào. Đây là ví dụ SplitDemo2 được sửa đổi để tách các chữ số thay thế:
package solutions; import java.util.regex.Pattern; public class SplitDemo2 { private static final String REGEX = "\\d"; private static final String INPUT = "one9two4three7four1five"; public static void main(String[] args) { Pattern p = Pattern.compile(REGEX); String[] items = p.split(INPUT); for (String s : items) { System.out.println(s); } } }
Kết quả:
one
two
three
four
five