"Безопасный способ" использования java matcher.replaceAll () / appendReplacement () - PullRequest
1 голос
/ 27 мая 2020

В большинстве случаев мы заменяем строковые сегменты, используя регулярное выражение, когда замещающий текст является переменной, поэтому в основном это неизвестно программисту.

Однако мы всегда забываем, что поведение java matcher.replaceAll () будет очень сильно зависеть от самой замены. Таким образом, замена не должна содержать никаких символов '$' или '\', чтобы получить результат наивный .

Например, следующий код throw "java .lang.IndexOutOfBoundsException: No group 2 »в случае, если переменная зарплата равна« 2 доллара ».

String salary = "$2";
Pattern p = Pattern.compile("SAL");
Matcher m = p.matcher("Salary: SAL");
String s = m.replaceAll(salary);
System.out.println(s);

Я знаю, что если знак« $ »экранирован символом« \ », то мы получим результат ожидаемый . Но опять же, '\' также следует экранировать с помощью '\'. Так что правильным решением будет:

String salary = "$2";
Pattern p = Pattern.compile("SAL");
Matcher m = p.matcher("Salary: SAL");
String s = m.replaceAll(salary.replace("\\", "\\\\").replace("$", "\\$"));
System.out.println(s);

Во-первых, это не так удобно в использовании, но и с точки зрения производительности не очень. (То же самое относится и к методу appendReplacement ().)

Итак, не могли бы вы порекомендовать более общее c решение проблемы?

1 Ответ

0 голосов
/ 27 мая 2020

В случае, если вы хотите заменить только указанную подстроку c на указанную буквальную последовательность замены, вы можете просто использовать String.replace(). Примерно так:

  String source = "Salary: SAL";
  String target = "SAL";
  String salary = "$2";
  String result = source.replace(target, salary);
  System.out.println(result); // prints "Salary: $2"

Стоит отметить, что он заменяет только буквальные последовательности подстрок и не будет работать, если target является регулярным выражением.

...