Sự khác biệt giữa so khớp () và find () trong Java Regex


250

Tôi đang cố gắng để hiểu sự khác biệt giữa matches()find().

Theo Javadoc, (từ những gì tôi hiểu), matches()sẽ tìm kiếm toàn bộ chuỗi ngay cả khi nó tìm thấy những gì nó đang tìm kiếm và find()sẽ dừng lại khi tìm thấy những gì nó đang tìm kiếm.

Nếu giả định đó là chính xác, tôi không thể thấy bất cứ khi nào bạn muốn sử dụng matches()thay vì find(), trừ khi bạn muốn đếm số lượng trận đấu mà nó tìm thấy.

Theo tôi, lớp String sau đó nên có find()thay vì matches()như một phương thức sẵn có.

Vì vậy, để tóm tắt:

  1. Là giả định của tôi đúng?
  2. Khi nào nó hữu ích để sử dụng matches()thay vì find()?

2
Xin lưu ý rằng việc gọi find()nhiều lần có thể trả về các kết quả khác nhau cho cùng một kết quả Matcher. Xem câu trả lời của tôi dưới đây.
L. Holanda

Câu trả lời:


300

matchescố gắng khớp biểu thức với toàn bộ chuỗi và ngầm định thêm ^vào lúc bắt đầu và $ở cuối mẫu của bạn, nghĩa là nó sẽ không tìm chuỗi con. Do đó đầu ra của mã này:

public static void main(String[] args) throws ParseException {
    Pattern p = Pattern.compile("\\d\\d\\d");
    Matcher m = p.matcher("a123b");
    System.out.println(m.find());
    System.out.println(m.matches());

    p = Pattern.compile("^\\d\\d\\d$");
    m = p.matcher("123");
    System.out.println(m.find());
    System.out.println(m.matches());
}

/* output:
true
false
true
true
*/

123là một chuỗi con của a123bnên find()phương pháp đầu ra sự thật. matches()chỉ 'thấy' a123bkhông giống 123và do đó xuất ra sai.


25
Câu trả lời này là sai lệch. matchers()không chỉ đơn giản là một find()ngụ ý xung quanh ^ và $. Xin lưu ý rằng việc gọi .find()nhiều lần có thể có kết quả khác nhau nếu không được đặt trước reset(), trong khi matches()sẽ luôn trả về cùng một kết quả. Xem câu trả lời của tôi dưới đây.
L. Holanda

80

matchestrả về true nếu toàn bộ chuỗi khớp với mẫu đã cho. findcố gắng tìm một chuỗi con phù hợp với mẫu.


35
Bạn có thể nói điều đó matches(p)giống như find("^" + p + "$")nếu điều đó rõ ràng hơn.
jensgram

4
Chỉ là một ví dụ để làm rõ câu trả lời: "[az] +" với chuỗi "123abc123" sẽ không sử dụng kết quả khớp () nhưng sẽ thành công khi sử dụng find ().
bezmax

3
@Max Chính xác, "123abc123".matches("[a-z]+")sẽ thất bại như mong "123abc123".find("^[a-z]+$")muốn. Quan điểm của tôi là, điều đó matches()phù hợp với một trận đấu hoàn chỉnh, giống như find()với cả neo bắt đầu và kết thúc.
jensgram

5
Pattern.compile("some pattern").matcher(str).matches()bằng vớiPattern.compile("^some pattern$").matcher(str).find()
AlexR

3
@AlexR / @jensgram: ...("some pattern").matcher(str).matches()không chính xác bằng ...("^some pattern$").matcher(str).find()đó của chỉ đúng trong cuộc gọi đầu tiên. Xem câu trả lời của tôi dưới đây.
L. Holanda

62

matches()sẽ chỉ trả về true nếu chuỗi đầy đủ được khớp. find()sẽ cố gắng tìm sự xuất hiện tiếp theo trong chuỗi con phù hợp với biểu thức chính quy. Lưu ý nhấn mạnh vào "tiếp theo". Điều đó có nghĩa là, kết quả của việc gọi find()nhiều lần có thể không giống nhau. Ngoài ra, bằng cách sử dụng, find()bạn có thể gọi start()để trả về vị trí mà chuỗi con được khớp.

final Matcher subMatcher = Pattern.compile("\\d+").matcher("skrf35kesruytfkwu4ty7sdfs");
System.out.println("Found: " + subMatcher.matches());
System.out.println("Found: " + subMatcher.find() + " - position " + subMatcher.start());
System.out.println("Found: " + subMatcher.find() + " - position " + subMatcher.start());
System.out.println("Found: " + subMatcher.find() + " - position " + subMatcher.start());
System.out.println("Found: " + subMatcher.find());
System.out.println("Found: " + subMatcher.find());
System.out.println("Matched: " + subMatcher.matches());

System.out.println("-----------");
final Matcher fullMatcher = Pattern.compile("^\\w+$").matcher("skrf35kesruytfkwu4ty7sdfs");
System.out.println("Found: " + fullMatcher.find() + " - position " + fullMatcher.start());
System.out.println("Found: " + fullMatcher.find());
System.out.println("Found: " + fullMatcher.find());
System.out.println("Matched: " + fullMatcher.matches());
System.out.println("Matched: " + fullMatcher.matches());
System.out.println("Matched: " + fullMatcher.matches());
System.out.println("Matched: " + fullMatcher.matches());

Sẽ xuất:

Tìm thấy: sai
Tìm thấy: đúng - vị trí 4
Tìm thấy: đúng - vị trí 17
Tìm thấy: đúng - vị trí 20
Tìm thấy: sai
Tìm thấy: sai
Khớp: sai
-----------
Đã tìm thấy: true - vị trí 0
Tìm thấy: sai
Tìm thấy: sai
Phù hợp: đúng
Phù hợp: đúng
Phù hợp: đúng
Phù hợp: đúng

Vì vậy, hãy cẩn thận khi gọi find()nhiều lần nếu Matcherđối tượng không được đặt lại, ngay cả khi regex được bao quanh ^$để khớp với chuỗi đầy đủ.


2
người bạn đời rất hữu ích
DockYard

6

find()sẽ xem xét chuỗi con so với biểu thức chính quy trong đó matches()sẽ xem xét biểu thức hoàn chỉnh.

find() sẽ trả về true chỉ khi chuỗi con của biểu thức khớp với mẫu.

public static void main(String[] args) {
        Pattern p = Pattern.compile("\\d");
        String candidate = "Java123";
        Matcher m = p.matcher(candidate);

        if (m != null){
            System.out.println(m.find());//true
            System.out.println(m.matches());//false
        }
    }

3

matches();không đệm, nhưng find()đệm. find()tìm kiếm đến cuối chuỗi trước, lập chỉ mục kết quả và trả về giá trị boolean và chỉ mục tương ứng.

Đó là lý do tại sao khi bạn có một mã như

1:Pattern.compile("[a-z]");

2:Pattern.matcher("0a1b1c3d4");

3:int count = 0;

4:while(matcher.find()){

5:count++: }

4: Công cụ regex sử dụng cấu trúc mẫu sẽ đọc qua toàn bộ mã của bạn (chỉ mục thành chỉ mục theo chỉ định regex[single character]để tìm ít nhất một kết quả khớp. Nếu tìm thấy kết quả khớp đó, nó sẽ được lập chỉ mục sau đó vòng lặp sẽ thực thi dựa trên kết quả được lập chỉ mục khác nếu nó không thực hiện tính toán trước như vậy matches(); không. Câu lệnh while sẽ không bao giờ thực thi do ký tự đầu tiên của chuỗi khớp không phải là một bảng chữ cái.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.