Cảm ơn mọi người đã trả lời!
Câu trả lời của Gizmo chắc chắn nằm ngoài hộp và giải pháp tuyệt vời, nhưng không may là không phù hợp vì định dạng không thể giới hạn đối với lớp Formatter trong trường hợp này.
Adam Paynter thực sự trở thành trung tâm của vấn đề, với mô hình phù hợp.
Peter Nix và Sean Bright đã có một giải pháp tuyệt vời để tránh tất cả sự phức tạp của regex, nhưng tôi cần phải nêu ra một số lỗi nếu có mã thông báo lỗi không được thực hiện. Tuy nhiên, cả về việc thực hiện regex và vòng lặp thay thế hợp lý, đây là câu trả lời tôi đưa ra (với một chút trợ giúp từ Google và câu trả lời hiện có, bao gồm cả nhận xét của Sean Bright về cách sử dụng nhóm (1) so với nhóm()):
private static Pattern tokenPattern = Pattern.compile("\\{([^}]*)\\}");
public static String process(String template, Map<String, Object> params) {
StringBuffer sb = new StringBuffer();
Matcher myMatcher = tokenPattern.matcher(template);
while (myMatcher.find()) {
String field = myMatcher.group(1);
myMatcher.appendReplacement(sb, "");
sb.append(doParameter(field, params));
}
myMatcher.appendTail(sb);
return sb.toString();
}
Nơi doParameter lấy giá trị ra khỏi bản đồ và chuyển đổi nó thành chuỗi và ném ngoại lệ nếu không có.
Cũng lưu ý rằng tôi đã thay đổi mẫu để tìm dấu ngoặc rỗng (tức là {}), vì đó là điều kiện lỗi được kiểm tra rõ ràng.
EDIT:
Lưu ý rằng appendReplacement không phải là bất khả tri về nội dung của chuỗi. Mỗi javadocs, nó nhận ra $ và dấu gạch chéo ngược là một ký tự đặc biệt, vì vậy tôi đã thêm một số thoát để xử lý mẫu đó ở trên. Không được thực hiện theo cách thức hiệu quả nhất, nhưng trong trường hợp của tôi nó không phải là một thỏa thuận đủ lớn để có giá trị cố gắng để vi-tối ưu hóa các sáng tạo chuỗi.
Nhờ nhận xét từ Alan M, điều này có thể được thực hiện đơn giản hơn để tránh các vấn đề ký tự đặc biệt của appendReplacement.
thử http://github.com/niesfisch/tokenreplacer/ – Marcel