Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> Java

Greedy Quantifiers ใน Java Regex

Greedy Quantifiers** เป็นค่าเริ่มต้น จับคู่มากที่สุดเท่าที่จะเป็นไปได้ (longest match) ถ้าจับคู่ไม่สำเร็จ จะย้อนกลับ (backtrack) ทีละตัว

Quantifierความหมาย
re*0 หรือมากกว่า
re?0 หรือ 1
re+1 หรือมากกว่า
re{n}n ครั้งพอดี
re{n,}อย่างน้อย n
re{n,m}n ถึง m

ตัวอย่าง: [0-9]+ (Greedy)

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

public class Test {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        System.out.println("Enter input text: ");
        String input = sc.nextLine();
        String regex = "[0-9]+";
        
        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(input);
        
        System.out.println("Matched text: ");
        while (matcher.find()) {
            System.out.println(matcher.group());
        }
    }
}

ผลลัพธ์

Enter input text: 45545
Matched text:
45545

อธิบาย

  • Input: "45545"
  • Regex [0-9]+ = greedy: จับคู่ตัวเลข 1+ หลัก มากที่สุด
  • แม้ "4", "45", "455", "4554" ก็จับคู่ได้ แต่ greedy เลือก "45545" (ยาวที่สุด)
  • หากมีหลายกลุ่มตัวเลข จะจับคู่แต่ละกลุ่มแยกกัน

ตัวอย่างเพิ่มเติม


Input: "abc123def456"
Regex: "[0-9]+"
Matches: "123", "456" (2 กลุ่ม แยกกัน)

Input: "123abc456"
Regex: ".*[0-9]+"
Greedy .* ดูด盡可能多 → "123abc456" ทั้งหมด (เพราะ [0-9]+ ยังจับคู่ 456 ได้)
Reluctant ".*?[0-9]+" → "123" (จับคู่น้อยที่สุด)

Greedy vs Reluctant vs Possessive

โหมดSyntaxพฤติกรรมBacktrack
Greedy* + ? {n,m}จับคู่มากที่สุดใช่
Reluctant*? +? ?? {n,m}?จับคู่น้อยที่สุดใช่ (ขยาย)
Possessive*+ ++ ?+ {n,m}+จับคู่มากที่สุดไม่

ปัญหา Catastrophic Backtracking

Greedy quantifiers ซ้อนกันอาจทำให้ backtracking มากเกินไป (exponential time):


// อันตราย: (a+)+b กับ input "aaaaaaaaaaaaac"
Pattern.compile("(a+)+b").matcher("aaaaaaaaaaaaac").matches(); // ช้ามาก

// แก้ด้วย possessive: (a++)+b
Pattern.compile("(a++)+b").matcher("aaaaaaaaaaaaac").matches(); // เร็ว (fail fast)

สรุป

  • Greedy = default, เหมาะสำหรับกรณีทั่วไป
  • Reluctant = เมื่อต้องการ match สั้นที่สุด
  • Possessive = ป้องกัน backtracking, เพิ่มประสิทธิภาพ