Один из вариантов для ваших текущих примеров - использовать чередование, чтобы сопоставить либо не цифру, либо точку, либо символ пробела, либо совпадать с точкой, за которой следует 1+ нецифров, и утверждать, что это не заканчивается цифрой.
[^\d.\s]+|\.[^\d]+(?!\d)\b
[
"123a.12",
"aaa12aa",
"12.aaa13",
"12.aaa "
].forEach(str => console.log(str.replace(/[^\d.\s]+|\.[^\d]+(?!\d)\b/g, '')));
Изменить после обновленного вопроса
Чтобы получить значения без конечных точек и 2 десятичных знаков, вы можете использовать replace и функцию обратного вызова.
Сначала замените все не цифры и точки пустым пробелом, используя [^\d.]+
Использование шаблона для получения первой точки и 2 следующих цифр. Используйте группы захвата, чтобы вернуть требуемое совпадение, проверив значение любой другой группы, кроме первой.
^(\d+)(?:\.+|(\.)\.*(\d)\.*(\d).*)$
Regex demo
strings = [
"123a.12",
"aaa12aa",
"12.aaa13",
"12.aaa",
"12.555",
"12....",
"12.",
"12.35.12.14",
"12.aaa.2.s.5"
].map(str => {
return str
.replace(/[^\d.]/g, '')
.replace(/^(\d+)(?:\.+|(\.)\.*(\d)\.*(\d).*)$/, function(m, g1, g2, g3, g4) {
return undefined !== g2 ? g1 + g2 + g3 + g4 : g1;
});
});
console.log(strings);