Можно ли заменить группы в Java regex?
У меня есть этот код, и я хочу знать, если я могу заменить только группы (не все шаблоны) в Java regex.
Код:
//...
Pattern p = Pattern.compile("(\\d).*(\\d)");
String input = "6 example input 4";
Matcher m = p.matcher(input);
if (m.find()) {
//Now I want replace group one ( (\\d) ) with number
//and group two (too (\\d) ) with 1, but I don't know how.
}
Ответы
Ответ 1
Используйте $n (где n - цифра), чтобы ссылаться на захваченные подпоследовательности в replaceFirst(...)
. Я предполагаю, что вы хотели заменить первую группу литеральной строкой "число", а вторую группу - значением первой группы.
Pattern p = Pattern.compile("(\\d)(.*)(\\d)");
String input = "6 example input 4";
Matcher m = p.matcher(input);
if (m.find()) {
// replace first number with "number" and second number with the first
String output = m.replaceFirst("number $2$1"); // number 46
}
Рассмотрим (\D+)
для второй группы вместо (.*)
. *
является жадным совпадением и сначала потребляет последнюю цифру. Затем совпадению придется отступить, когда он поймет, что окончательный (\d)
не имеет ничего общего, прежде чем он сможет соответствовать последней цифре.
Ответ 2
Вы можете использовать Matcher#start(group)
и Matcher#end(group)
для создания общего метода замены:
public static String replaceGroup(String regex, String source, int groupToReplace, String replacement) {
return replaceGroup(regex, source, groupToReplace, 1, replacement);
}
public static String replaceGroup(String regex, String source, int groupToReplace, int groupOccurrence, String replacement) {
Matcher m = Pattern.compile(regex).matcher(source);
for (int i = 0; i < groupOccurrence; i++)
if (!m.find()) return source; // pattern not met, may also throw an exception here
return new StringBuilder(source).replace(m.start(groupToReplace), m.end(groupToReplace), replacement).toString();
}
public static void main(String[] args) {
// replace with "%" what was matched by group 1
// input: aaa123ccc
// output: %123ccc
System.out.println(replaceGroup("([a-z]+)([0-9]+)([a-z]+)", "aaa123ccc", 1, "%"));
// replace with "!!!" what was matched the 4th time by the group 2
// input: a1b2c3d4e5
// output: a1b2c3d!!!e5
System.out.println(replaceGroup("([a-z])(\\d)", "a1b2c3d4e5", 2, 4, "!!!"));
}
Проверьте онлайн-демо.
Ответ 3
Добавьте третью группу, добавив parens вокруг .*
, затем замените подпоследовательность на "number" + m.group(2) + "1"
. например:.
String output = m.replaceFirst("number" + m.group(2) + "1");
Ответ 4
Для получения позиций группы вы можете использовать методы matcher.start() и matcher.end(). Поэтому, используя эти позиции, вы можете легко заменить любой текст.