ความแตกต่างระหว่างการจับคู่ () และค้นหา () ใน Java Regex


250

ฉันพยายามที่จะเข้าใจความแตกต่างระหว่างและmatches()find()

อ้างอิงจาก Javadoc (จากสิ่งที่ฉันเข้าใจ) matches()จะค้นหาสตริงทั้งหมดแม้ว่าจะพบสิ่งที่ต้องการและfind()จะหยุดเมื่อพบสิ่งที่ต้องการ

หากข้อสันนิษฐานนั้นถูกต้องฉันจะไม่เห็นทุกครั้งที่คุณต้องการใช้matches()แทนfind()เว้นแต่คุณจะต้องการนับจำนวนการแข่งขันที่พบ

ในความคิดของฉันคลาส String นั้นควรมีfind()แทนที่จะmatches()เป็นวิธีการ inbuilt

ดังนั้นเพื่อสรุป:

  1. สมมติฐานของฉันถูกต้องหรือไม่
  2. เมื่อมันเป็นประโยชน์ที่จะใช้matches()แทนfind()?

2
โปรดทราบว่าการโทรหลายครั้งอาจส่งคืนผลลัพธ์ที่แตกต่างกันสำหรับเดียวกันfind() Matcherดูคำตอบของฉันด้านล่าง
L. Holanda

คำตอบ:


300

matchesพยายามจับคู่นิพจน์กับสตริงทั้งหมดและเพิ่ม^ที่จุดเริ่มต้นและ$ตอนท้ายของรูปแบบโดยปริยายหมายความว่าจะไม่ค้นหาซับสตริง ดังนั้นผลลัพธ์ของรหัสนี้:

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
*/

123เป็นย่อยของa123bดังนั้นfind()วิธีการออกผลลัพธ์ที่แท้จริง matches()เพียง 'เห็น' a123bซึ่งไม่เหมือนกับ123และทำให้ผลลัพธ์เป็นเท็จ


25
คำตอบนี้ทำให้เข้าใจผิด matchers()ไม่ได้เป็นเพียงแค่find()มีนัยโดยรอบ ^ และ $ โปรดทราบว่าการโทร.find()มากกว่าหนึ่งครั้งอาจมีผลลัพธ์ที่แตกต่างกันหากไม่นำหน้าด้วยreset()ในขณะที่matches()จะส่งกลับผลลัพธ์เดียวกันเสมอ ดูคำตอบของฉันด้านล่าง
L. Holanda

80

matchesคืนค่าจริงถ้าสตริงทั้งหมดตรงกับรูปแบบที่กำหนด findพยายามค้นหาสตริงย่อยที่ตรงกับรูปแบบ


35
คุณสามารถพูดได้ว่าmatches(p)มันเหมือนกับfind("^" + p + "$")ที่ชัดเจนกว่า
jensgram

4
เพียงตัวอย่างเพื่อชี้แจงคำตอบ: "[az] +" กับสตริง "123abc123" จะล้มเหลวในการใช้การจับคู่ () แต่จะประสบความสำเร็จในการใช้ find ()
bezmax

3
@ Max แน่นอน"123abc123".matches("[a-z]+")จะล้มเหลวตามที่"123abc123".find("^[a-z]+$")ต้องการ จุดของฉันคือที่matches()ไปสำหรับการแข่งขันที่สมบูรณ์เช่นเดียวfind()กับจุดเริ่มต้นและสิ้นสุด
jensgram

5
Pattern.compile("some pattern").matcher(str).matches()เท่ากับPattern.compile("^some pattern$").matcher(str).find()
AlexR

3
@AlexR / @jensgram: ...("some pattern").matcher(str).matches()จะไม่เท่ากับ...("^some pattern$").matcher(str).find()ที่จริงเพียงในสายแรก ดูคำตอบของฉันด้านล่าง
L. Holanda

62

matches()จะส่งคืนจริงถ้าจับคู่สตริงทั้งหมดเท่านั้น find()จะพยายามค้นหาการเกิดขึ้นครั้งถัดไปภายในซับสตริงที่ตรงกับ regex สังเกตการเน้นที่ "ตัวถัดไป" นั่นหมายความว่าผลลัพธ์ของการโทรfind()หลายครั้งอาจไม่เหมือนกัน นอกจากนี้โดยใช้find()คุณสามารถโทรstart()กลับตำแหน่งย่อยที่ถูกจับคู่

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());

จะส่งออก:

พบ: เท็จ
พบ: จริง - ตำแหน่ง 4
ค้นพบ: จริง - ตำแหน่ง 17
ค้นพบ: จริง - ตำแหน่ง 20
พบ: เท็จ
พบ: เท็จ
จับคู่: เท็จ
-----------
ค้นพบ: จริง - ตำแหน่ง 0
พบ: เท็จ
พบ: เท็จ
จับคู่: จริง
จับคู่: จริง
จับคู่: จริง
จับคู่: จริง

ดังนั้นควรระมัดระวังเมื่อโทรfind()หลายครั้งหากMatcherวัตถุไม่ได้ถูกรีเซ็ตแม้ว่า Regex จะล้อมรอบด้วย^และ$จับคู่กับสตริงทั้งหมด


2
เพื่อนที่เป็นประโยชน์มาก
DockYard

6

find()จะพิจารณาสตริงย่อยเทียบกับการแสดงออกปกติที่matches()จะพิจารณาการแสดงออกที่สมบูรณ์

find() จะส่งกลับค่าจริงหากสตริงย่อยของนิพจน์ตรงกับรูปแบบ

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();ไม่บัฟเฟอร์ แต่find()บัฟเฟอร์ find()ค้นหาส่วนท้ายของสตริงก่อนสร้างดัชนีผลลัพธ์และส่งคืนค่าบูลีนและดัชนีที่เกี่ยวข้อง

นั่นคือเหตุผลที่เมื่อคุณมีรหัสเช่น

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

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

3:int count = 0;

4:while(matcher.find()){

5:count++: }

ที่4: เอ็นจิ้น regex ที่ใช้โครงสร้างรูปแบบจะอ่านรหัสทั้งหมดของคุณ (ดัชนีไปยังดัชนีตามที่ระบุโดยregex[single character]เพื่อค้นหาการแข่งขันอย่างน้อยหนึ่งครั้งหากพบการจับคู่ดังกล่าวจะได้รับการจัดทำดัชนีแล้วลูปจะดำเนินการตาม ผลลัพธ์ที่จัดทำดัชนีเป็นอย่างอื่นหากไม่ได้ทำการคำนวณล่วงหน้าเช่นmatches()ใดไม่คำสั่ง while จะไม่ดำเนินการเนื่องจากอักขระตัวแรกของสตริงที่ตรงกันไม่ใช่ตัวอักษร

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.