Java RegEx: Pattern සහ Matcher Classes - සම්පූර්ණ මාර්ගෝපදේශය

ආයුබෝවන්, Software Engineering වලට ආස කරන හැමෝටම!
අද අපි කතා කරන්න යන්නේ ගොඩක් දෙනෙක්ට ටිකක් සංකීර්ණ වගේ පෙනුනත්, නිතරම වගේ අපේ දෛනික වැඩ වලට නැතුවම බැරි වෙන වැදගත් subject එකක් ගැන. ඒ තමයි Regular Expressions (RegEx). විශේෂයෙන්ම, අපි බලමු Java වල මේ RegEx Patterns සහ Matchers කොහොමද effectively use කරන්නේ කියලා. බය වෙන්න එපා! මං ඔයාලට පුළුවන් තරම් සරලවයි, Practical examples එක්කයි මේක කියලා දෙන්නම්.
ඔබ Software Engineer කෙනෙක්ද, Student කෙනෙක්ද, නැත්නම් Coding කරන්න ආස කෙනෙක්ද, මේ Article එක ඔයාට ගොඩක් වටිනවා කියල විශ්වාසයි. මොකද data validation, text processing, search and replace වගේ වැඩ වලදී RegEx නැතුව බෑ කියල ඔයාලට තේරෙයි.
RegEx කියන්නේ මොකක්ද?
සරලවම කිව්වොත්, RegEx කියන්නේ string එකක් ඇතුළේ තියෙන text patterns හොයන්න, match කරන්න, නැත්නම් manipulate කරන්න පාවිච්චි කරන special character sequence එකක්. සාමාන්යයෙන් ඔයාල word processors වල search box එකේ "find and replace" කරද්දි මේ RegEx වල සරල versions පාවිච්චි වෙනවා. ඒත් Software Development වලදී RegEx කියන්නේ ඊට වඩා ගොඩක් දේවල් කරන්න පුළුවන් powerful tool එකක්.
- Data Validation: Email address එකක් හරි format එකේ තියෙනවද, phone number එකක් හරියට type කරලද කියලා බලන්න.
- Text Processing: ලොකු text file එකකින් specific information ටිකක් extract කරගන්න, උදාහරණයක් විදියට log files වලින් error messages විතරක් තෝරගන්න.
- Search and Replace: String එකක තියෙන particular patterns අඳුනගෙන ඒව වෙනස් කරන්න.
- Parsing: Structured data (like URLs, dates) break down කරලා අවශ්ය කොටස් ටික අරගන්න.
Java වලදී RegEx operations කරන්න Pattern සහ Matcher කියන classes දෙක තමයි ප්රධාන වශයෙන්ම use කරන්නේ. මේ දෙක තියෙන්නේ java.util.regex
package එක ඇතුළේ.
Java වල Pattern Class එක
RegEx එකක් Java වලදී පාවිච්චි කරන්න නම්, මුලින්ම අපි ඒ RegEx එක Pattern
object එකක් විදියට compile කරගන්න ඕනේ. මේකෙන් වෙන්නේ අපේ RegEx එක Java Virtual Machine (JVM) එකට තේරෙන විදියට optimize කරන එකයි. මේක කරන්නේ Pattern.compile()
method එකෙන්.
import java.util.regex.Pattern;
public class PatternExample {
public static void main(String[] args) {
// "abc" කියන pattern එක compile කරනවා
Pattern pattern = Pattern.compile("abc");
System.out.println("Pattern compiled successfully: " + pattern.pattern());
}
}
මේ compile()
method එකට String
එකක් විදියට අපේ RegEx pattern එක දෙනවා. මතක තියාගන්න, Pattern
object එක immutable. ඒ කියන්නේ හදුවට පස්සේ අපිට ඒක වෙනස් කරන්න බෑ.
Pattern Flags
අපිට පුළුවන් compile()
method එකට දෙවෙනි argument එකක් විදියට flags පාවිච්චි කරන්න. මේ flags වලින් RegEx එකේ හැසිරීම වෙනස් කරන්න පුළුවන්. පොදු flags කීපයක් තමයි මේ:
Pattern.CASE_INSENSITIVE
: Case එක ගැන බලන්නේ නැතුව match කරනවා (a-A, b-B වගේ).Pattern.MULTILINE
: Multi-line text එකකදී^
(start of line) සහ$
(end of line) anchors හැසිරෙන විදිය වෙනස් කරනවා.Pattern.DOTALL
:.
(dot) එක new line characters (\n
) එක්කත් match කරන්න පුළුවන් වෙනවා. (සාමාන්යයෙන්.
එකෙන් new line match වෙන්නේ නෑ).
import java.util.regex.Pattern;
public class PatternFlagsExample {
public static void main(String[] args) {
String text = "Hello World\nhello java";
// Case-insensitive matching
Pattern pattern1 = Pattern.compile("hello", Pattern.CASE_INSENSITIVE);
System.out.println("Pattern 1 (case-insensitive): " + pattern1.pattern());
// Multiline matching
Pattern pattern2 = Pattern.compile("^hello", Pattern.MULTILINE);
System.out.println("Pattern 2 (multiline): " + pattern2.pattern());
}
}
Matcher Class එකේ වැඩ
Pattern
object එකක් compile කරගත්තට පස්සේ, අපිට පුළුවන් ඒකෙන් Matcher
object එකක් හදාගන්න. Matcher
object එක තමයි අපේ input text එකේ RegEx pattern එක හොයන්න, match කරන්න, සහ වෙනස් කරන්න පාවිච්චි කරන්නේ.
import java.util.regex.Pattern;
import java.util.regex.Matcher;
public class MatcherExample {
public static void main(String[] args) {
String text = "Software Engineering is fun. Software is great.";
Pattern pattern = Pattern.compile("Software");
Matcher matcher = pattern.matcher(text); // Matcher object එක හදාගන්නවා
System.out.println("Matcher created for pattern: " + pattern.pattern());
}
}
matcher()
method එකට input string එක දෙනවා. දැන් අපි බලමු Matcher
class එකේ ප්රධාන methods කීපයක් ගැන:
1. matches()
මේ method එකෙන් බලන්නේ මුළු input string එකම අපේ RegEx pattern එකට match වෙනවද කියලා. boolean
value එකක් return කරනවා.
import java.util.regex.Pattern;
import java.util.regex.Matcher;
public class MatchesExample {
public static void main(String[] args) {
String email1 = "[email protected]";
String email2 = "invalid-email";
// Simple email pattern (not fully robust for all cases)
String emailPattern = "^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,6}$";
Pattern pattern = Pattern.compile(emailPattern);
Matcher matcher1 = pattern.matcher(email1);
System.out.println("'" + email1 + "' matches: " + matcher1.matches()); // Output: true
Matcher matcher2 = pattern.matcher(email2);
System.out.println("'" + email2 + "' matches: " + matcher2.matches()); // Output: false
}
}
2. find()
මේ method එකෙන් input string එකේ ඊළඟ pattern occurrence එක හොයනවා. boolean
value එකක් return කරනවා. එකම string එකේ pattern එක කීප වතාවක් තියෙනවද කියලා බලන්න loop එකක් ඇතුළේ මේක පාවිච්චි කරන්න පුළුවන්.
import java.util.regex.Pattern;
import java.util.regex.Matcher;
public class FindExample {
public static void main(String[] args) {
String text = "I have 3 apples and 10 bananas.";
Pattern pattern = Pattern.compile("\\d+"); // Match one or more digits
Matcher matcher = pattern.matcher(text);
while (matcher.find()) {
System.out.println("Found: " + matcher.group() +
" at start index: " + matcher.start() +
" and end index: " + matcher.end());
}
// Output:
// Found: 3 at start index: 9 and end index: 10
// Found: 10 at start index: 21 and end index: 23
}
}
3. group()
find()
method එක true return කරාට පස්සේ, group()
method එකෙන් match වුණ text portion එක return කරනවා. Group number එකක් දීලත් match වුණ Sub-group එකක් ගන්න පුළුවන් (capturing groups). group(0)
කියන්නේ මුළු match එකම, group(1)
කියන්නේ පළවෙනි capturing group එක, වගේ.
import java.util.regex.Pattern;
import java.util.regex.Matcher;
public class GroupExample {
public static void main(String[] args) {
String text = "Date: 2023-10-26";
// Pattern with capturing groups for year, month, and day
Pattern pattern = Pattern.compile("(\\d{4})-(\\d{2})-(\\d{2})");
Matcher matcher = pattern.matcher(text);
if (matcher.find()) {
System.out.println("Full match: " + matcher.group(0)); // 2023-10-26
System.out.println("Year: " + matcher.group(1)); // 2023
System.out.println("Month: " + matcher.group(2)); // 10
System.out.println("Day: " + matcher.group(3)); // 26
}
}
}
4. replaceAll()
Input string එකේ pattern එකට match වෙන හැම occurrence එකක්ම given replacement string එකකින් replace කරනවා.
import java.util.regex.Pattern;
import java.util.regex.Matcher;
public class ReplaceAllExample {
public static void main(String[] args) {
String text = "Cat, Dog, Cat, Mouse";
Pattern pattern = Pattern.compile("Cat");
Matcher matcher = pattern.matcher(text);
String newText = matcher.replaceAll("Lion");
System.out.println("Original text: " + text);
System.out.println("New text: " + newText); // Output: Lion, Dog, Lion, Mouse
}
}
5. appendReplacement()
සහ appendTail()
මේ methods දෙක ගොඩක් වැදගත් වෙන්නේ complex replacements කරන්න ඕන වෙලාවට. උදාහරණයක් විදියට, match වුණ හැම pattern එකක්ම එකම string එකකින් replace නොකර, match එක අනුව වෙනස් replacement එකක් දෙන්න ඕන නම්.
import java.util.regex.Pattern;
import java.util.regex.Matcher;
import java.lang.StringBuffer; // Not StringBuilder for this
public class AppendReplacementExample {
public static void main(String[] args) {
String text = "The price of item1 is $10 and item2 is $20.";
Pattern pattern = Pattern.compile("\\$(\\d+)"); // Match $ followed by digits, capture digits
Matcher matcher = pattern.matcher(text);
StringBuffer result = new StringBuffer(); // Use StringBuffer for appendReplacement
while (matcher.find()) {
int price = Integer.parseInt(matcher.group(1)); // Get the captured price
// Replace with price in LKR (example conversion)
matcher.appendReplacement(result, "LKR " + (price * 300));
}
matcher.appendTail(result); // Append the rest of the string after the last match
System.out.println("Original text: " + text);
System.out.println("Modified text: " + result.toString());
// Output: Modified text: The price of item1 is LKR 3000 and item2 is LKR 6000.
}
}
මේ උදාහරණයෙන් පේනවා, කොහොමද අපි dollar values LKR බවට convert කරන්නේ කියලා. මෙතන StringBuffer
එකක් පාවිච්චි කරලා තියෙන්නේ, appendReplacement()
method එක StringBuffer
එකක් expect කරන නිසා. (Not StringBuilder
).
සැබෑ ලෝකේ උදාහරණ
1. Email Validation
මේක ගොඩක් පොදු භාවිතයක්. User input validate කරද්දි email addresses වල validity බලන්න RegEx පාවිච්චි කරනවා.
import java.util.regex.Pattern;
import java.util.regex.Matcher;
public class EmailValidator {
private static final String EMAIL_REGEX =
"^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,6}$"; // Basic email pattern
private static final Pattern pattern = Pattern.compile(EMAIL_REGEX);
public static boolean isValidEmail(String email) {
Matcher matcher = pattern.matcher(email);
return matcher.matches();
}
public static void main(String[] args) {
System.out.println("[email protected] is valid: " + isValidEmail("[email protected]")); // true
System.out.println("[email protected] is valid: " + isValidEmail("[email protected]")); // true
System.out.println("invalid-email is valid: " + isValidEmail("invalid-email")); // false
System.out.println("@domain.com is valid: " + isValidEmail("@domain.com")); // false
}
}
2. Phone Number Extraction
ලොකු text block එකකින් specific format එකක තියෙන phone numbers extract කරගන්න මේක පාවිච්චි කරන්න පුළුවන්.
import java.util.regex.Pattern;
import java.util.regex.Matcher;
public class PhoneNumberExtractor {
// Matches Sri Lankan phone numbers (e.g., 071-1234567, +94-77-1234567)
private static final String PHONE_REGEX =
"(?:\\+94|0)?(7\\d{8})"; // Capture 7 and next 8 digits (07x-xxxxxxx or +947x-xxxxxxx)
public static void main(String[] args) {
String text = "Contact us at 0771234567 or +94719876543. My office number is 011-2345678 (landline - not matched here).";
Pattern pattern = Pattern.compile(PHONE_REGEX);
Matcher matcher = pattern.matcher(text);
System.out.println("Extracted Phone Numbers:");
while (matcher.find()) {
System.out.println("Found: " + matcher.group(0) + " (Number part: " + matcher.group(1) + ")");
}
// Output:
// Extracted Phone Numbers:
// Found: 0771234567 (Number part: 771234567)
// Found: +94719876543 (Number part: 719876543)
}
}
මේ උදාහරණයේදී, (?:\\+94|0)?
කියන්නේ +94
නැත්නම් 0
තියෙන්නත් පුළුවන්, නැතිවෙන්නත් පුළුවන් කියන එක. (7\\d{8})
කියන්නේ 7
න් පටන් අරන් තව digits 8ක් තියෙන group එකක් අල්ලගන්න කියන එක. මේක තමයි අපේ phone number එකේ mobile part එක. group(0)
කියන්නේ මුළු match එකම, group(1)
කියන්නේ අපේ (7\\d{8})
capturing group එක.
නිගමනය
Java වල Pattern
සහ Matcher
classes කියන්නේ text manipulation වලට තියෙන powerful tools දෙකක්. මේවා හොඳින් තේරුම් අරන් පාවිච්චි කරන්න පුළුවන් නම්, data validation, parsing, සහ text processing වගේ ගොඩක් වැඩ පහසුවෙන්, effectively කරන්න පුළුවන්. මුලින් RegEx ටිකක් අමාරු වගේ පෙනුනත්, පුරුදු වෙද්දි මේකේ තියෙන බලය තේරෙයි.
වැදගත්ම දේ තමයි practice කරන එක. Online RegEx testers ගොඩක් තියෙනවා (e.g., regex101.com, regexr.com). ඒව පාවිච්චි කරලා patterns හදලා බලන්න, test කරන්න. ඔබේ Code එකේ නිතරම වගේ මේ Pattern, Matcher classes පාවිච්චි කරන්න පුරුදු වෙන්න.
මේ Article එක ඔයාලට වැදගත් වුණා කියලා හිතනවා. මොනවා හරි ප්රශ්න තියෙනවා නම්, නැත්නම් අලුත් දෙයක් ඉගෙනගත්තා නම්, පහළින් comment එකක් දාගෙන යන්න අමතක කරන්න එපා. අපි තවදුරටත් කතා කරමු!
Happy Coding!