Я не могу поверить, что это не простая решаемая проблема, но эй, вот мой удар в этом
(?:[^%]|^)(?:(%%)+|)(%)(?:[^%])
Чтобы очистить сообщение перед его передачей в String.format, вы можете использовать следующее
Pattern p = Pattern.compile("(?:[^%]|^)(?:(%%)+|)(%)(?:[^%])");
Matcher m1 = p.matcher(log);
StringBuffer buf = new StringBuffer();
while (m1.find())
m1.appendReplacement(buf, log.substring(m1.start(), m1.start(2)) + "%%" + log.substring(m1.end(2), m1.end()));
// Return the sanitised message
String escapedString = m1.appendTail(buf).toString();
Обратите внимание, что это работает с любым количеством символов форматирования, поэтому он заменит% на %%, %%% на %%%%, %%%%% на %%%%%% и т. Д.
Он оставит все уже экранированные символы в одиночку (например, %%, %%%% и т. Д.)