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

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

Xuất bản trong nhóm
Chúng tôi xin giới thiệu với bạn bản dịch hướng dẫn ngắn gọn về các biểu thức chính quy trong 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 4 - 1 Biểu thức chính quy trong Java, Phần 1 Biểu thức chính quy trong Java, Phần 2 Biểu thức chính quy trong Java, Phần 3

Phương pháp làm việc với các nhóm bị bắt

Mã nguồn ứng dụng RegexDemobao gồm lệnh gọi phương thức m.group(). Phương thức này group()là một trong một số phương thức của lớp Matchernhằm làm việc với các nhóm bị bắt:
  • Phương thức này int groupCount()trả về số lượng nhóm đã chụp trong mẫu trình phân giải. Con số này không tính đến nhóm chụp đặc biệt số 0, tương ứng với toàn bộ mẫu.

  • Phương thức String group()trả về các ký tự của kết quả khớp trước đó được tìm thấy. Để báo cáo tìm kiếm thành công một chuỗi trống, phương thức này trả về một chuỗi trống. Nếu trình phân giải chưa thực hiện tra cứu hoặc thao tác tra cứu trước đó không thành công thì một ngoại lệ sẽ được đưa ra IllegalStateException.

  • Phương thức này String group(int group)tương tự như phương thức trước, ngoại trừ việc nó trả về các ký tự của kết quả khớp trước đó, được ghi lại bởi số nhóm được chỉ định bởi tham số group. Lưu ý rằng điều này group(0)tương đương với group(). Nếu mẫu không có nhóm được chụp với số đã cho, phương thức sẽ đưa ra một ngoại lệ IndexOutOfBoundsException. Nếu trình phân giải chưa thực hiện tra cứu hoặc thao tác tra cứu trước đó không thành công thì một ngoại lệ sẽ được đưa ra IllegalStateException.

  • Phương thức này String group(String name)trả về các ký tự của kết quả khớp trước đó được tìm thấy, được nhóm tên nắm bắt. Nếu tên nhóm đã chụp không có trong mẫu, một ngoại lệ sẽ được đưa ra IllegalArgumentException. Nếu trình phân giải chưa thực hiện tra cứu hoặc thao tác tra cứu trước đó không thành công thì một ngoại lệ sẽ được đưa ra IllegalStateException.

Ví dụ sau minh họa cách sử dụng của groupCount()và các phương thức group(int group):
Pattern p = Pattern.compile("(.(.(.)))");
Matcher m = p.matcher("abc");
m.find();
System.out.println(m.groupCount());
for (int i = 0; i <= m.groupCount(); i++)
System.out.println(i + ": " + m.group(i));
Kết quả thực hiện:
3
0: abc
1: abc
2: bc
3: c
Biểu thức chính quy trong Java, Phần 4 - 2

Phương pháp xác định vị trí khớp

Lớp này Matchercung cấp một số phương thức trả về vị trí bắt đầu và kết thúc của một kết quả khớp:
  • Phương thức int start()trả về vị trí bắt đầu của kết quả khớp được tìm thấy trước đó. Nếu trình phân giải chưa thực hiện tra cứu hoặc thao tác tra cứu trước đó không thành công thì một ngoại lệ sẽ được đưa ra IllegalStateException.

  • Phương thức này int start(int group)tương tự như phương thức trước, nhưng trả về vị trí bắt đầu của kết quả khớp trước đó được tìm thấy cho nhóm có số được chỉ định bởi tham số group. Nếu mẫu không có nhóm được chụp với số đã cho, phương thức sẽ đưa ra một ngoại lệ IndexOutOfBoundsException. Nếu trình phân giải chưa thực hiện tra cứu hoặc thao tác tra cứu trước đó không thành công thì một ngoại lệ sẽ được đưa ra IllegalStateException.

  • Phương thức này int start(String name)tương tự như phương thức trước, nhưng trả về vị trí bắt đầu của kết quả khớp trước đó được tìm thấy cho nhóm có tên name. Nếu nhóm đã chụp namekhông có trong mẫu, một ngoại lệ sẽ được đưa ra IllegalArgumentException. Nếu trình phân giải chưa thực hiện tra cứu hoặc thao tác tra cứu trước đó không thành công thì một ngoại lệ sẽ được đưa ra IllegalStateException.

  • Phương thức int end()trả về vị trí của ký tự cuối cùng của kết quả khớp trước đó được tìm thấy cộng với 1. Nếu trình so khớp chưa thực hiện kết quả khớp hoặc thao tác tìm kiếm trước đó không thành công, một ngoại lệ sẽ được đưa ra IllegalStateException.

  • Phương thức này int end(int group)tương tự như phương thức trước, nhưng trả về vị trí kết thúc của kết quả khớp trước đó được tìm thấy cho nhóm có số được chỉ định bởi tham số group. Nếu mẫu không có nhóm được chụp với số đã cho, phương thức sẽ đưa ra một ngoại lệ IndexOutOfBoundsException. Nếu trình phân giải chưa thực hiện tra cứu hoặc thao tác tra cứu trước đó không thành công thì một ngoại lệ sẽ được đưa ra IllegalStateException.

  • Phương thức này int end(String name)tương tự như phương thức trước, nhưng trả về vị trí kết thúc của kết quả khớp trước đó được tìm thấy cho nhóm có tên name. Nếu nhóm đã chụp namekhông có trong mẫu, một ngoại lệ sẽ được đưa ra IllegalArgumentException. Nếu trình phân giải chưa thực hiện tra cứu hoặc thao tác tra cứu trước đó không thành công thì một ngoại lệ sẽ được đưa ra IllegalStateException.

Ví dụ sau đây minh họa hai phương pháp vị trí khớp để xuất ra vị trí khớp bắt đầu/kết thúc cho nhóm chụp số 2:
Pattern p = Pattern.compile("(.(.(.)))");
Matcher m = p.matcher("abcabcabc");
while (m.find())
{
   System.out.println("Найдено " + m.group(2));
   System.out.println("  начинается с позиции " + m.start(2) +
                      " и заканчивается на позиции " + (m.end(2) - 1));
   System.out.println();
}
Đầu ra của ví dụ này là như sau:
Найдено bc
начинается с позиции 1 и заканчивается на позиции 2
Найдено bc
начинается с позиции 4 и заканчивается на позиции 5
Найдено bc
начинается с позиции 7 и заканчивается на позиции 8

Các phương thức của lớp PatternSyntaxException

Một phiên bản của lớp PatternSyntaxExceptionmô tả lỗi cú pháp trong biểu thức chính quy. Ném ra một ngoại lệ như vậy từ các phương thức compile()matches()lớp Patternvà được hình thành thông qua hàm tạo sau: PatternSyntaxException(String desc, String regex, int index) Hàm tạo này lưu trữ mô tả đã chỉ định ( desc), biểu thức chính quy ( regex) và vị trí xảy ra lỗi cú pháp. Nếu không xác định được vị trí của lỗi cú pháp thì giá trị indexđược đặt thành -1. Rất có thể, bạn sẽ không bao giờ cần tạo các phiên bản của tệp PatternSyntaxException. Tuy nhiên, bạn sẽ cần trích xuất các giá trị trên khi tạo thông báo lỗi được định dạng. Để làm điều này, bạn có thể sử dụng các phương pháp sau:
  • Phương thức String getDescription()trả về mô tả lỗi cú pháp.
  • Phương thức int getIndex()trả về vị trí xảy ra lỗi hoặc -1 nếu không xác định được vị trí đó.
  • Phương thức String getPattern()trả về một biểu thức chính quy không hợp lệ.
Ngoài ra, phương thức kế thừa String getMessage()trả về một chuỗi nhiều dòng với các giá trị được trả về từ các phương thức trước đó cùng với dấu hiệu trực quan về nơi xảy ra lỗi cú pháp trong mẫu. Lỗi cú pháp là gì? Đây là một ví dụ: java RegexDemo (?itree Treehouse Trong trường hợp này, chúng ta đã quên chỉ định siêu ký tự dấu ngoặc đơn đóng ( )) trong biểu thức cờ lồng nhau. Đây là kết quả đầu ra từ lỗi này:
regex = (?itree
input = Treehouse
Неправильное регулярное выражение: Unknown inline modifier near index 3
(?itree
   ^
Описание: Unknown inline modifier
Позиция: 3
Неправильный шаблон: (?itree

Xây dựng các ứng dụng biểu thức chính quy hữu ích bằng API Regex

Biểu thức chính quy cho phép bạn tạo các ứng dụng xử lý văn bản mạnh mẽ. Trong phần này, chúng tôi sẽ giới thiệu cho bạn hai ứng dụng tiện dụng, hy vọng sẽ khuyến khích bạn khám phá thêm về các lớp và phương thức API Regex. Phụ lục thứ hai giới thiệu về Lexan: một thư viện mã có thể tái sử dụng để thực hiện phân tích từ vựng. Biểu thức chính quy trong Java, Phần 4 - 3

Biểu thức và tài liệu thông thường

Tài liệu hóa là một trong những nhiệm vụ bắt buộc khi phát triển phần mềm chuyên nghiệp. May mắn thay, biểu thức chính quy có thể giúp bạn trong nhiều khía cạnh của việc tạo tài liệu. Mã trong Liệt kê 1 trích xuất các dòng chứa các nhận xét kiểu C một dòng và nhiều dòng từ một tệp nguồn và ghi chúng vào một tệp khác. Để mã hoạt động, các nhận xét phải nằm trên cùng một dòng. Liệt kê 1. Truy xuất các nhận xét
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;

public class ExtCmnt
{
   public static void main(String[] args)
   {
      if (args.length != 2)
      {
         System.err.println("Способ применения: java ExtCmnt infile outfile");
         return;
      }

      Pattern p;
      try
      {
         // Следующий шаблон определяет многострочные комментарии,
         // располагающиеся в одной строке (например, /* одна строка */)
            // и однострочные комментарии (например, // Howая-то строка).
            // Комментарий может располагаться в любом месте строки.

         p = Pattern.compile(".*/\\*.*\\*/|.*//.*$");
      }
      catch (PatternSyntaxException pse)
      {
         System.err.printf("Синтаксическая ошибка в регулярном выражении: %s%n", pse.getMessage());
         System.err.printf("Описание ошибки: %s%n", pse.getDescription());
         System.err.printf("Позиция ошибки: %s%n", pse.getIndex());
         System.err.printf("Ошибочный шаблон: %s%n", pse.getPattern());
         return;
      }

      try (FileReader fr = new FileReader(args[0]);
           BufferedReader br = new BufferedReader(fr);
           FileWriter fw = new FileWriter(args[1]);
           BufferedWriter bw = new BufferedWriter(fw))
      {
         Matcher m = p.matcher("");
         String line;
         while ((line = br.readLine()) != null)
         {
            m.reset(line);
            if (m.matches()) /* Должна соответствовать вся строка */
            {
               bw.write(line);
               bw.newLine();
            }
         }
      }
      catch (IOException ioe)
      {
         System.err.println(ioe.getMessage());
         return;
      }
   }
}
Phương thức main()trong Liệt kê 1 trước tiên kiểm tra cú pháp dòng lệnh chính xác và sau đó biên dịch một biểu thức chính quy được thiết kế để phát hiện các nhận xét một dòng và nhiều dòng thành một đối tượng lớp Pattern. Nếu không có ngoại lệ nào được nêu ra PatternSyntaxException, phương thức main()sẽ mở tệp nguồn, tạo tệp đích, lấy một trình so khớp để khớp từng dòng được đọc với mẫu và sau đó đọc từng dòng của tệp nguồn. Đối với mỗi dòng, nó được khớp với một mẫu nhận xét. Nếu thành công, phương thức này main()sẽ ghi chuỗi (theo sau là một dòng mới) vào tệp đích (chúng tôi sẽ đề cập đến logic I/O của tệp trong hướng dẫn Java 101 trong tương lai). Biên dịch Liệt kê 1 như sau: javac ExtCmnt.java Chạy ứng dụng với tệp ExtCmnt.javalàm đầu vào: java ExtCmnt ExtCmnt.java out Bạn sẽ nhận được các kết quả sau trong tệp ra:
// Следующий шаблон определяет многострочные комментарии,
 // располагающиеся в одной строке (например, /* одна строка */)
    // и однострочные комментарии (например, // Howая-то строка).
    // Комментарий может располагаться в любом месте строки.
p = Pattern.compile(".*/\\*.*\\*/|.*//.*$");
    if (m.matches()) /* Должна соответствовать вся строка */
Trong chuỗi mẫu .*/\\*.*\\*/|.*//.*$, siêu ký tự ống |đóng vai trò như một toán tử OR logic, cho biết rằng trình so khớp nên sử dụng toán hạng bên trái của cấu trúc biểu thức chính quy đã cho để tìm kết quả khớp trong văn bản so khớp. Nếu không có kết quả khớp nào, trình so khớp sẽ sử dụng toán hạng bên phải từ cấu trúc biểu thức chính quy đã cho cho một nỗ lực tìm kiếm khác (các siêu ký tự dấu ngoặc đơn trong nhóm đã bắt cũng tạo thành một toán tử logic). 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