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

ประเภทของ Quantifiers ใน Java Regex

Quantifiers ใช้ระบุจำนวนครั้งของการเกิดซ้ำของ pattern ใน Regular Expression Java รองรับ 3 ประเภทหลัก:

1. Greedy Quantifiers (ขี้หิ้ว - เริ่มต้นค่าเริ่มต้น)

Match มากที่สุดเท่าที่จะเป็นไปได้ (longest match) หาก match ไม่สำเร็จ จะ backtrack (ย้อนกลับ) ตัวอักษรทีละตัวจนกว่าจะ match ได้

Quantifier ความหมาย
X? X เกิด 0 หรือ 1 ครั้ง
X* X เกิด 0 ครั้งขึ้นไป
X+ X เกิด 1 ครั้งขึ้นไป
X{n} X เกิด n ครั้งพอดี
X{n,} X เกิด n ครั้งขึ้นไป
X{n,m} X เกิด n ถึง m ครั้ง

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

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

Output

Enter input text: abc123def456
Matched text:
123
456

2. Reluctant (Non-greedy) Quantifiers (ไม่ขี้หิ้ว)

Match น้อยที่สุดเท่าที่จะเป็นไปได้ (shortest match) เริ่มจาก match ตัวเดียว แล้วค่อยเพิ่มทีละตัวจนกว่าจะ match ได้ ใช้โดยใส่ ? หลัง greedy quantifier

Quantifier ความหมาย
X?? X เกิด 0 หรือ 1 ครั้ง (reluctant)
X*? X เกิด 0 ครั้งขึ้นไป (reluctant)
X+? X เกิด 1 ครั้งขึ้นไป (reluctant)
X{n,}? X เกิด n ครั้งขึ้นไป (reluctant)
X{n,m}? X เกิด n ถึง m ครั้ง (reluctant)

ตัวอย่าง Reluctant: [0-9]+?

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

        while (matcher.find()) {
            System.out.println(matcher.group());
        }
    }
}

Output

Enter input text: 12345678
1
2
3
4
5
6
7
8

คำอธิบาย: +? match ตัวเลขทีละตัว เพราะพยายาม match น้อยที่สุด

3. Possessive Quantifiers (ครอบครอง - ไม่ย้อนกลับ)

คล้าย Greedy (match มากที่สุด) แต่ ไม่ backtrack เลย หาก match ไม่สำเร็จ จะ fail ทันที ใช้โดยใส่ + หลัง greedy quantifier

Quantifier ความหมาย
X?+ X เกิด 0 หรือ 1 ครั้ง (possessive)
X*+ X เกิด 0 ครั้งขึ้นไป (possessive)
X++ X เกิด 1 ครั้งขึ้นไป (possessive)
X{n,}+ X เกิด n ครั้งขึ้นไป (possessive)
X{n,m}+ X เกิด n ถึง m ครั้ง (possessive)

ตัวอย่าง Possessive: [0-9]++

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

        while (matcher.find()) {
            System.out.println(matcher.group());
        }
    }
}

Output

Enter input text: 45678
45678

ตารางเปรียบเทียบพฤติกรรม

Input Regex Match Result ประเภท
"abc123" [a-z]+ "abc" Greedy
"abc123" [a-z]+? "a" Reluctant
"abc123" [a-z]++ "abc" Possessive
"aaab" a+b "aaab" (match) Greedy + backtrack
"aaab" a++b No match (a++ กินหมด aaa แล้วไม่เหลือ b) Possessive - no backtrack

เมื่อไหร่ควรใช้แบบไหน?

  • Greedy - ใช้ส่วนใหญ่ ค่าเริ่มต้น เหมาะสำหรับการ match แบบปกติ
  • Reluctant - เมื่อต้องการ match น้อยที่สุด เช่น parsing HTML tags <.+?>
  • Possessive - เพื่อประสิทธิภาพและป้องกัน catastrophic backtracking เมื่อแน่ใจว่า pattern ต่อท้ายไม่ overlap