Nội Dung Thực Hành
Bài viết tập trung vào việc áp dụng biểu thức chính quy (Regex) để giải quyết các vấn đề phổ biến như tìm kiếm chuỗi con, thay đổi nội dung dựa trên vị trí mẫu, xử lý dữ liệu động thông qua hàm callback, và phân chia đoạn văn bản. Sau đây là minh chứng cụ thể cho ba nền tảng phát triển khác nhau về cú pháp và API được cung cấp.
Giải Pháp Cho Java
Trong môi trường Java, lớp Pattern và Matcher thuộc thư viện java.util.regex đóng vai trò quan trọng. Dưới đây là ví dụ sử dụng phương thức thay thế nhóm và chuyển đổi dữ liệu.
import java.util.Arrays;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class RegexDemonstration {
public static void main(String[] args) {
String strInput = "123-4567-89,987-6543-21";
Pattern pattern = Pattern.compile("\\d{3}-(\\d{4})-\\d{2}");
Matcher matcher = pattern.matcher(strInput);
// Kiểm tra trùng lặp và hiển thị nhóm
int count = 0;
while (matcher.find()) {
if (count == 0) System.out.println("Kết quả tìm thấy:");
for (int j = 0; j <= matcher.groupCount(); j++) {
System.out.printf("Nhóm %d, Vị trí %d : %s%n", count, j, matcher.group(j));
}
count++;
}
// Thay thế vị trí các số với nhau
System.out.println(strInput.replaceFirst("(\\d+)-(\\d+)-(\\d+)", "$3-$1-$2"));
// Hàm callback giả lập đảo ngược số
StringBuilder buffer = new StringBuilder();
pattern = Pattern.compile("\\d+");
matcher = pattern.matcher(strInput);
while (matcher.find()) {
String reversed = new StringBuilder(matcher.group(0)).reverse().toString();
matcher.appendReplacement(buffer, reversed);
}
matcher.appendTail(buffer);
System.out.println(buffer.toString());
// Chia nhỏ chuỗi
pattern = Pattern.compile("%(?:begin|next|end)%");
String splitSource = "%begin%hello%next%world%end%";
System.out.println(Arrays.asList(pattern.split(splitSource)));
}
}
// Kết quả đầu ra mẫu:
// [Nhóm 0, Vị trí 0 : 123-4567-89]
// [Nhóm 0, Vị trí 1 : 4567]
// 89-123-4567,987-6543-21
// 321-7654-98,789-3456-12
// [, hello, world]
Triển Khai Trong C#
Ngôn ngữ C# cung cấp module System.Text.RegularExpressions. Việc xử lý được tối ưu hóa qua các câu lệnhLINQ và hàm đánh giá (evaluator).
using System;
using System.Linq;
using System.Text.RegularExpressions;
namespace TechSamples.RegexApp
{
class Program
{
static void Main(string[] args)
{
var data = "123-4567-89,987-6543-21";
var rx = new Regex(@"\d{3}-(\d{4})-\d{2}");
// Đếm và liệt kê kết quả
var matches = rx.Matches(data).Cast<Match>().ToList();
if (matches.Any()) Console.WriteLine("Có kết quả:");
foreach (var item in matches.Select((m, i) => new { Index = i, Match = m }))
foreach (var grp in item.Match.Groups.Cast<Group>().Select((g, j) => new { Idx = j, Value = g.Value }))
Console.WriteLine($"Group {item.Index},{grp.Idx} : {grp.Value}");
// Đổi chỗ tham chiếu chuỗi
var rxSwap = new Regex(@"(\d+)-(\d+)-(\d+)");
Console.WriteLine(rxSwap.Replace(data, "$3-$1-$2"));
// Đảo ngược ký tự số
var rxDigit = new Regex(@"\d+");
data = rxDigit.Replace(data, m =>
{
var chars = m.Value.ToCharArray();
Array.Reverse(chars);
return new string(chars);
});
Console.WriteLine(data);
// Tách chuỗi biên
var rxSplit = new Regex(@"%(?:begin|next|end)%");
string splitStr = "%begin%hello%next%world%end%";
Console.WriteLine(string.Join(",", rxSplit.Split(splitStr)));
}
}
}
/* Đầu ra:
Found matches:
group 0,0 : 123-4567-89
group 0,1 : 4567
89-123-4567,21-987-6543
321-7654-98,789-3456-12
,hello,world,*/
Cấu Hình C++ Với Boost Regex
Đối với C++, thư viện Boost mang lại sức mạnh biểu thức chính quy tương thích với các tính năng hiện đại của C++. Chúng ta sử dụng iterator để duyệt qua các kết quả khớp.
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <boost/regex.hpp>
#include <boost/algorithm/string/join.hpp>
using namespace std;
using boost::regex;
int main()
{
string txt = "123-4567-89,987-6543-21";
regex r(R"(\d{3}-(\d{4})-\d{2})");
sregex_iterator iterBeg(txt.begin(), txt.end(), r);
sregex_iterator iterEnd;
int idx = 0;
cout << "Tìm thấy:" << endl;
for(auto it = iterBeg; it != iterEnd; ++it, ++idx)
for(size_t k = 0; k < it->size(); ++k)
cout << "nhóm " << idx << "," << k << " : " << (*it)[k] << endl;
// Thay thế mẫu
regex r2(R"((\d+)-(\d+)-(\d+))");
cout << regex_replace(txt, r2, "$3-$1-$2") << endl;
// Lambda function cho việc thay thế phức tạp
regex r3(R"(\d+)");
txt = regex_replace(txt, r3, [](const smatch& match){
string temp = match.str();
reverse(temp.begin(), temp.end());
return temp;
});
cout << txt << endl;
// Phân tách chuỗi tùy chỉnh
regex r4("%(?:begin|next|end)%");
vector<string> parts;
for(auto tok = sregex_token_iterator(txt.begin(), txt.end(), r4, -1); tok != sregex_token_iterator(); ++tok)
parts.push_back(tok->str());
cout << boost::join(parts, ",") << endl;
}
// Output Expected:
// Found:
// group 0,0 : 123-4567-89
// group 0,1 : 4567
// 89-123-4567,21-987-6543
// 321-7654-98,789-3456-12
// ,hello,world