В Java вы можете попробовать что-то вроде этого:
Pattern.compile("^(\\s*)(?:\\.)*(\\w)").matcher(input).replaceFirst("$1.$2");
Это даст следующие результаты:
" GOTO ok1" -> " .GOTO ok1",
" .GOTO ok1" -> " .GOTO ok1",
"GOTO ok1" -> ".GOTO ok1",
" ..GOTO ok1" -> " .GOTO ok1",
" " -> " "
Matcher.replaceFirst заменяет первое вхождение выкройки с предоставленной заменой. $1
и $2
в строке замены - это ссылки на группы захвата в шаблоне:
заданная строка " ....GOTO ok1"
:
- полное совпадение с шаблоном:
" ....G"
- группа 1:
" "
(ведущие пробелы) - группа 2:
"G"
(первая буква) - таким образом,
" ....G"
заменяется на " .G"
На практике вы бы предпочли скомпилировать шаблон один раз и использовать его повторно:
class RegexTest {
private final static Pattern PATTERN = Pattern.compile("^(\\s*)(?:\\.)*(\\w)");
@Test
void test() {
var examples = Map.of(
" GOTO ok1", " .GOTO ok1",
" .GOTO ok1", " .GOTO ok1",
"GOTO ok1", ".GOTO ok1",
" ..GOTO ok1", " .GOTO ok1",
" ", " "
);
examples.forEach((input, expected) -> {
assertEquals(expected, PATTERN.matcher(input).replaceFirst("$1.$2"));
});
}
}
С точки зрения производительности регулярные выражения довольно дороги, наиболее эффективным было бы простое l oop:
String format(String in) {
StringBuilder builder = new StringBuilder();
for(int i=0; i<in.length(); i++) {
switch (in.charAt(i)) {
case ' ':
builder.append(' ');
break;
case '.':
break;
default:
builder.append(".").append(in.substring(i));
return builder.toString();
}
}
return builder.toString();
}