Как замаскировать номера счетов в тексте файла?

Метод должен читать файл и маскировать номера счетов. Должны быть видны только первые 4 и последние 4 цифры (1234 **** **** 5678). Метод должен содержать регулярное выражение для поиска счета. Как реализовать этот метод так, чтоб он вернул текст с маскированными номерами счетов?

File file = new File(
                "data.txt");
        try (Scanner scanner = new Scanner(file)) {
            while (scanner.hasNextLine()) {
                String line = scanner.nextLine();
                Pattern p = Pattern.compile("\\b(\\d){4}\\s(\\d){4}\\s(\\d){4}\\s(\\d){4}\\b+");
                Matcher m = p.matcher(line);
                while (m.find()) {
                    char[] textCharMass = line.substring(m.start(), m.end()).toCharArray();
                    char[] encryptedText = new char[textCharMass.length];
                    for (int i = 0; i < textCharMass.length; i++) {
                        if (i > 4 && i < 14 && textCharMass[i] != ' ') {
                            encryptedText[i] = (char) 42;
                        } else {
                            encryptedText[i] = textCharMass[i];
                        }
                    }
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

Ответы (1 шт):

Автор решения: PotroNik

UPD: Изменены группы захвата в позитивных просмотрах назад и вперед на не захватываемые. В связи с этой проблемой при замене не правильно подставлялись данные

Автоматически сформированный код на regex101.com

import java.util.regex.Matcher;
import java.util.regex.Pattern;

final String regex = "(?<=(?:[^\\d]|^))(\\d{4}[ \\t])(?:\\d{4}[ \\t]){2}(\\d{4})(?=(?:[^\\d]|$))";
final String string = "1234 1234 1234 1234\n"
     + "1234 5678 9101 1121\n"
     + "1234 84848 5454 4888\n"
     + "1111 2222 5555 4444\n"
     + "1111 2222 5555 44444\n"
     + "11111 2222 5555 4444\n"
     + "asa1111 2222 5555 4444dasda";
final String subst = "$1**** **** $2";

final Pattern pattern = Pattern.compile(regex, Pattern.MULTILINE);
final Matcher matcher = pattern.matcher(string);

// The substituted value will be contained in the result variable
final String result = matcher.replaceAll(subst);

System.out.println("Substitution result: " + result);

Подробнее о регулярном выражении:

(?<=(?:[^\d]|^))(\d{4}[ \t])(?:\d{4}[ \t]){2}(\d{4})(?=(?:[^\d]|$))

Где (?<=(?:[^\d]|^)) позитивный просмотр назад, и если у нас идет не цифра или начало строки перед группой, то захватываем.
Первая группа захвата (\d{4}[ \t]) 4 идущие подряд цифры, после них пробел или табуляция
Не захватываемая группа (?:\d{4}[ \t]){2} 4 идущие подряд цифры, после них пробел или табуляция, группа повторяется 2 раза
Вторая группа захвата (\d{4}) 4 цифры идущие подряд
Далее позитивный просмотр вперед, что у нас нет дальше цифр или это конец строки (?=(?:[^\d]|$))

В замене возвращаем первую и вторую захваченные группы, а между ними символы
$1**** **** $2

Посмотреть пример можно тут: https://regex101.com/r/8elJV1/2

→ Ссылка