четвъртък, 12 юни 2008 г.

String.replaceAll одисея

Колега от нашия екип настъпа интересна Java-ешка мотика. Имаме следния примерен безобиден код:

String template = "Our price: amount";
String price = "$9.99";
String msg = template.replaceAll("amount", price);
System.out.println(msg);


Искаме да заменим в шаблончето amount с истинската цена. При изпълнение обаче получаваме:

Exception in thread "main" java.lang.IndexOutOfBoundsException: No group 9
at java.util.regex.Matcher.group(Matcher.java:463)
at java.util.regex.Matcher.appendReplacement(Matcher. java:730)
at java.util.regex.Matcher.replaceAll(Matcher.java:80 6)
at java.lang.String.replaceAll(String.java:2000)


Опааа! К'о стана? При внимателно четене на документацията се оказва, че $ и \ се използват за заместване на прихванати низове в регулярния израз в първия аргумент на replaceAll (/foo(bar)baz/ => $1 = bar):


Note that backslashes (\) and dollar signs ($) in the replacement string may cause the results to be different than if it were being treated as a literal replacement string. Dollar signs may be treated as references to captured subsequences as described above, and backslashes are used to escape literal characters in the replacement string.

В Java 5 и по-нова са "решили" проблема - за да направите прост replaceAll без необходимост от регулярен израз използвайте...

replace(CharSequence, CharSequence) // String implements CharSequence

Интуитивно, нали?. Ако държите е на регулярените изразчета като шаблон за търсене, и да нямате проблем с низа за заместване използвайте:

template.replaceAll("pattern", Matcher.quoteReplacement("replacement text"));

Няма коментари: