JavaRush /Blog Java /Random-VI /Biểu thức chính quy trong Java, Phần 1

Biểu thức chính quy trong Java, Phần 1

Xuất bản trong nhóm
Chúng tôi xin gửi đến bạn bản dịch hướng dẫn ngắn gọn về các biểu thức chính quy bằng ngôn ngữ Java, do Jeff Friesen viết cho trang web JavaWorld . Để dễ đọc, chúng tôi chia bài viết thành nhiều phần. Biểu thức chính quy trong Java, Phần 1 - 1

Sử dụng API biểu thức chính quy trong các chương trình Java để nhận biết và mô tả các mẫu

Ký tự của Java và các kiểu dữ liệu chuỗi khác nhau cung cấp hỗ trợ ở mức độ thấp cho việc khớp mẫu, nhưng việc sử dụng chúng cho mục đích này thường làm tăng thêm độ phức tạp đáng kể của mã. Mã đơn giản hơn và hiệu quả hơn có được bằng cách sử dụng API Regex ("API biểu thức chính quy"). Hướng dẫn này sẽ giúp bạn bắt đầu với biểu thức chính quy và API Regex. Trước tiên, chúng ta sẽ thảo luận chung về ba lớp thú vị nhất trong gói java.util.regex, sau đó xem xét bên trong lớp Patternvà khám phá các cấu trúc khớp mẫu phức tạp của nó. Chú ý: Bạn có thể tải xuống mã nguồn (được tạo bởi Jeff Friesen cho trang JavaWorld) của ứng dụng demo từ bài viết này từ đây .

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

Biểu thức chính quy (biểu thức chính quy/regex/regexp) là một chuỗi là mẫu mô tả một tập hợp chuỗi nhất định. Mẫu xác định hàng nào thuộc về tập hợp. Mẫu này bao gồm các ký tự chữ và siêu ký tự—các ký tự có ý nghĩa đặc biệt chứ không phải nghĩa đen. So khớp mẫu là tìm kiếm văn bản để tìm kết quả khớp, nghĩa là các chuỗi khớp với mẫu biểu thức chính quy. Java hỗ trợ khớp mẫu thông qua API Regex của nó. API này bao gồm ba lớp: Pattern, MatcherPatternSyntaxException, nằm trong gói java.util.regex:
  • các đối tượng lớp Pattern, còn được gọi là các mẫu, được biên dịch các biểu thức chính quy.
  • đối tượng lớp Matcherhoặc trình so khớp là cơ chế giải thích mẫu để tìm kết quả khớp trong chuỗi ký tự (đối tượng có lớp triển khai giao diện java.lang.CharSequencevà đóng vai trò là nguồn văn bản).
  • Các đối tượng lớp PatternSyntaxExceptionđược sử dụng để mô tả các mẫu biểu thức chính quy không hợp lệ.
Java cũng cung cấp hỗ trợ cho việc khớp mẫu thông qua các phương thức khác nhau của java.lang.String. Ví dụ: hàm chỉ boolean matches (String regex)trả về truenếu chuỗi gọi khớp chính xác với biểu thức chính quy regex.
Phương pháp thuận tiện
matches()và các phương thức thuận tiện theo định hướng biểu thức chính quy khác của lớp Stringđược triển khai bên trong theo cách tương tự như API Regex.

RegexBản demo

Tôi đã tạo một ứng dụng RegexDemođể thể hiện các biểu thức chính quy Java và các phương thức khác nhau của các tệp Pattern, MatcherPatternSyntaxException. Dưới đây là mã nguồn của ứng dụng demo này. Liệt kê 1. Trình diễn biểu thức chính quy
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
public class RegexDemo
{
   public static void main(String[] args)
   {
      if (args.length != 2)
      {
         System.err.println("usage: java RegexDemo regex input");
         return;
      }
      // Преобразуем символьные последовательности начала новой строки (\n) в символы начала строки.
      args[1] = args[1].replaceAll("\\\\n", "\n");
      try
      {
         System.out.println("regex = " + args[0]);
         System.out.println("input = " + args[1]);
         Pattern p = Pattern.compile(args[0]);
         Matcher m = p.matcher(args[1]);
         while (m.find())
            System.out.println("Found [" + m.group() + "] starting at "
                               + m.start() + " and ending at " + (m.end() - 1));
      }
      catch (PatternSyntaxException pse)
      {
         System.err.println("Неправильное регулярное выражение: " + pse.getMessage());
         System.err.println("Описание: " + pse.getDescription());
         System.err.println("Позиция: " + pse.getIndex());
         System.err.println("Неправильный шаблон: " + pse.getPattern());
      }
   }
}
Điều đầu tiên mà một phương thức mainlớp thực hiện RegexDemolà kiểm tra dòng lệnh của nó. Nó yêu cầu hai đối số: đối số đầu tiên là biểu thức chính quy và đối số thứ hai là văn bản đầu vào trong đó biểu thức chính quy sẽ được tìm kiếm. Bạn có thể cần sử dụng ký tự dòng mới trong văn bản đầu vào (\n). Điều này chỉ có thể được thực hiện bằng cách chỉ định ký tự \theo sau là ký tự n. Hàm main()chuyển đổi chuỗi ký tự này thành giá trị Unicode 10. Biểu thức chính quy trong Java, Phần 1 - 2Phần lớn mã RegexDemođược đặt trong tệp try-catch. Khối tryđầu tiên xuất ra biểu thức chính quy đã cho và văn bản đầu vào, sau đó tạo một đối tượng Patternlưu trữ biểu thức chính quy đã biên dịch (các biểu thức chính quy được biên dịch để cải thiện hiệu suất khớp mẫu). Bộ so khớp được trích xuất từ ​​đối tượng Patternvà được sử dụng để tìm kiếm các kết quả khớp lặp đi lặp lại cho đến khi tìm thấy tất cả. Khối catchgọi một số phương thức lớp PatternSyntaxExceptionđể lấy thông tin hữu ích về ngoại lệ. Thông tin này được xuất ra tuần tự tới luồng đầu ra. Không cần phải biết chi tiết về cách thức hoạt động của mã: chúng sẽ rõ ràng hơn khi chúng ta nghiên cứu API ở phần thứ hai của bài viết. Tuy nhiên, bạn phải biên dịch Liệt kê 1. Lấy mã từ Liệt kê 1, rồi gõ lệnh sau tại dấu nhắc lệnh để biên dịch RegexDemo: javac RegexDemo.java

Lớp Pattern và các cấu trúc của nó

Lớp Pattern, lớp đầu tiên trong ba lớp tạo nên API Regex, là một biểu diễn được biên dịch của một biểu thức chính quy. Tài liệu SDK lớp Patternmô tả nhiều cấu trúc biểu thức chính quy khác nhau, nhưng nếu bạn không chủ động sử dụng biểu thức chính quy thì các phần của tài liệu này có thể gây nhầm lẫn. Định lượng là gì và sự khác biệt giữa định lượng tham lam, miễn cưỡng và sở hữu là gì? Các lớp ký tự, bộ so khớp ranh giới, tham chiếu ngược và biểu thức cờ được nhúng là gì? Tôi sẽ trả lời những câu hỏi này và những câu hỏi khác trong các phần sau.

Chuỗi chữ

Cấu trúc biểu thức chính quy đơn giản nhất là một chuỗi ký tự. Để khớp mẫu thành công, một số phần của văn bản đầu vào phải khớp với mẫu của cấu trúc đó. Hãy xem xét ví dụ sau: java RegexDemo apple applet Trong ví dụ này, chúng tôi đang cố gắng tìm kết quả khớp cho một mẫu appletrong văn bản đầu vào applet. Kết quả sau đây cho thấy kết quả phù hợp được tìm thấy:
regex = apple
input = applet
Found [apple] starting at 0 and ending at 4
Chúng tôi thấy ở đầu ra biểu thức chính quy và văn bản đầu vào, sau đó là dấu hiệu phát hiện thành công appletrong applet. Ngoài ra, vị trí bắt đầu và kết thúc của trận đấu này lần lượt được đưa ra: 04. Vị trí bắt đầu cho biết vị trí đầu tiên trong văn bản nơi tìm thấy kết quả khớp và vị trí kết thúc cho biết điểm cuối cùng của kết quả khớp. Bây giờ, giả sử chúng ta đưa ra dòng lệnh sau: java RegexDemo apple crabapple Lần này chúng ta nhận được kết quả sau, với vị trí bắt đầu và kết thúc khác nhau:
regex = apple
input = crabapple
Found [apple] starting at 4 and ending at 8
Nếu không, với và appletdưới dạng biểu thức chính quy apple- văn bản đầu vào, sẽ không tìm thấy kết quả khớp nào. Toàn bộ biểu thức chính quy phải khớp nhau, nhưng trong trường hợp này, văn bản đầu vào không chứa tsau apple. Biểu thức chính quy trong Java, Phần 1 - 3

Siêu ký tự

Các cấu trúc biểu thức chính quy thú vị hơn kết hợp các ký tự chữ với siêu ký tự. Ví dụ: trong một biểu thức chính quy a.b, siêu ký tự dấu chấm (.)có nghĩa là bất kỳ ký tự nào nằm giữa avà b. Hãy xem xét ví dụ sau: java RegexDemo .ox "The quick brown fox jumps over the lazy ox." Ví dụ này sử dụng .oxcả biểu thức chính quy và The quick brown fox jumps over the lazy ox.văn bản đầu vào. RegexDemotìm kiếm văn bản để tìm các kết quả khớp bắt đầu bằng bất kỳ ký tự nào và kết thúc bằng ký ox.tự nào. Kết quả thực hiện của nó như sau:
regex = .ox
input = The quick brown fox jumps over the lazy ox.
Found [fox] starting at 16 and ending at 18
Found [ ox] starting at 39 and ending at 41
Trong kết quả đầu ra, chúng ta thấy hai kết quả khớp: foxox(có ký tự khoảng trắng ở phía trước). Siêu ký tự . khớp với một ký tự ftrong trường hợp đầu tiên và khoảng trắng trong trường hợp thứ hai. Điều gì xảy ra nếu bạn thay thế nó .oxbằng một siêu ký tự .? Đó là những gì chúng ta nhận được nhờ dòng lệnh sau: java RegexDemo . "The quick brown fox jumps over the lazy ox." Vì siêu ký tự dấu chấm khớp với bất kỳ ký tự nào, nên RegexDemosẽ xuất ra các kết quả khớp được tìm thấy cho tất cả các ký tự (bao gồm cả ký tự dấu chấm cuối cùng) của văn bản đầu vào:
regex = .
input = The quick brown fox jumps over the lazy ox.
Found [T] starting at 0 and ending at 0
Found [h] starting at 1 and ending at 1
Found [e] starting at 2 and ending at 2
Found [ ] starting at 3 and ending at 3
Found [q] starting at 4 and ending at 4
Found [u] starting at 5 and ending at 5
Found [i] starting at 6 and ending at 6
Found [c] starting at 7 and ending at 7
Found [k] starting at 8 and ending at 8
Found [ ] starting at 9 and ending at 9
Found [b] starting at 10 and ending at 10
Found [r] starting at 11 and ending at 11
Found [o] starting at 12 and ending at 12
Found [w] starting at 13 and ending at 13
Found [n] starting at 14 and ending at 14
Found [ ] starting at 15 and ending at 15
Found [f] starting at 16 and ending at 16
Found [o] starting at 17 and ending at 17
Found [x] starting at 18 and ending at 18
Found [ ] starting at 19 and ending at 19
Found [j] starting at 20 and ending at 20
Found [u] starting at 21 and ending at 21
Found [m] starting at 22 and ending at 22
Found [p] starting at 23 and ending at 23
Found [s] starting at 24 and ending at 24
Found [ ] starting at 25 and ending at 25
Found [o] starting at 26 and ending at 26
Found [v] starting at 27 and ending at 27
Found [e] starting at 28 and ending at 28
Found [r] starting at 29 and ending at 29
Found [ ] starting at 30 and ending at 30
Found [t] starting at 31 and ending at 31
Found [h] starting at 32 and ending at 32
Found [e] starting at 33 and ending at 33
Found [ ] starting at 34 and ending at 34
Found [l] starting at 35 and ending at 35
Found [a] starting at 36 and ending at 36
Found [z] starting at 37 and ending at 37
Found [y] starting at 38 and ending at 38
Found [ ] starting at 39 and ending at 39
Found [o] starting at 40 and ending at 40
Found [x] starting at 41 and ending at 41
Found [.] starting at 42 and ending at 42
Trích dẫn siêu ký tự
Để chỉ định .hoặc bất kỳ siêu ký tự nào khác làm ký tự chữ trong cấu trúc biểu thức chính quy, bạn phải thoát khỏi nó theo một trong các cách sau:
  • đặt trước nó một ký tự dấu gạch chéo ngược;
  • Đặt siêu ký tự này ở giữa \Q\E(ví dụ: \Q.\E).
Hãy nhớ sao chép bất kỳ ký tự nào xuất hiện trong chuỗi ký tự, chẳng hạn như String regex = "\\.";dấu gạch chéo ngược (ví dụ: \\.hoặc \\Q.\\E). Không sao chép các dấu gạch chéo ngược đó là một phần của đối số dòng lệnh.

Lớp nhân vật

Đôi khi bạn phải giới hạn những kết quả phù hợp mà bạn đang tìm kiếm trong một bộ ký tự cụ thể. Ví dụ: tìm kiếm văn bản cho các nguyên âm a, e, và , với mỗi lần xuất hiện icủa một chữ cái nguyên âm được coi là khớp. Để giải quyết những vấn đề như vậy, chúng ta sẽ được trợ giúp bởi các lớp ký tự xác định các tập hợp ký tự giữa các siêu ký tự của dấu ngoặc vuông ( ). Lớp này hỗ trợ các lớp ký tự đơn giản, các lớp phạm vi, các lớp nghịch đảo, hợp, giao và trừ. Bây giờ chúng ta sẽ xem xét tất cả chúng. ou[ ]Pattern

Lớp nhân vật đơn giản

Một lớp ký tự đơn giản bao gồm các ký tự được đặt cạnh nhau và chỉ khớp với các ký tự đó. Ví dụ: lớp [abc]khớp với các ký tự a, bc. Hãy xem xét ví dụ sau: java RegexDemo [csw] cave Như bạn có thể thấy từ kết quả, trong ví dụ này chỉ ccó ký tự khớp với cave:
regex = [csw]
input = cave
Found [c] starting at 0 and ending at 0

Các lớp ký tự đảo ngược

Một lớp ký tự đảo ngược bắt đầu bằng một siêu ký tự ^và chỉ khớp với những ký tự không có trong đó. Ví dụ: lớp [^abc]khớp với tất cả các ký tự ngoại trừ a, bc. Hãy xem xét ví dụ sau: java RegexDemo "[^csw]" cave Lưu ý rằng trên hệ điều hành (Windows) của tôi cần có dấu ngoặc kép vì shell coi chúng ^là ký tự thoát. Như bạn có thể thấy, trong ví dụ này chỉ có các ký tự a, vvà được tìm thấy e, có các ký tự trùng khớp trong cave:
regex = [^csw]
input = cave
Found [a] starting at 1 and ending at 1
Found [v] starting at 2 and ending at 2
Found [e] starting at 3 and ending at 3

Các lớp ký tự phạm vi

Một lớp ký tự phạm vi bao gồm hai ký tự được phân tách bằng dấu gạch nối ( -). Tất cả các ký tự, bắt đầu bằng ký tự ở bên trái dấu gạch nối và kết thúc bằng ký tự ở bên phải, đều là một phần của phạm vi. Ví dụ: phạm vi [a-z]khớp với tất cả các chữ cái Latinh viết thường. Điều này tương đương với việc định nghĩa một lớp đơn giản [abcdefghijklmnopqrstuvwxyz]. Hãy xem xét ví dụ sau: java RegexDemo [a-c] clown Ví dụ này sẽ chỉ khớp với ký tự ckhớp trong clown:
regex = [a-c]
input = clown
Found [c] starting at 0 and ending at 0
Biểu thức chính quy trong Java, Phần 2 Biểu thức chính quy trong Java, Phần 3 Biểu thức chính quy trong Java, Phần 4 Biểu thức chính quy trong Java, Phần 5
Bình luận
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION