Найдите и замените регулярное выражение для маски ввода идентификационного номера

Я хотел бы помочь создать маскировку ввода с помощью регулярных выражений поиска и замены для следующего варианта использования:

Пользователь вводит 11 цифр своего идентификационного номера, и вывод будет иметь следующий формат:

\d\d\d.\d\d\d.\d\d\d-\d\d

Первая попытка

Найти: (\d{3})(\d{3})(\d{3})(\d{2})

Заменить: $1.$2.$3-$4

Это работает только после того, как пользователь введет все 11 цифр. Однако я хочу, чтобы точки и тире появлялись, когда пользователь печатает.

Вторая попытка

Найти: (\d{1,3})(\d{1,3})(\d{1,3})(\d{1,2})

Заменить: $1.$2.$3-$4

Как только пользователь вводит четвертую цифру, а результат получается таким \d.\d.\d-\d

Третья попытка

Найти: (\d{3})(\d{0,3})(\d{0,3})(\d{0,2})

Заменить: $1.$2.$3-$4

Как только пользователь вводит третью цифру, а результат получается таким \d\d\d\..-

Код:

Краткое описание кода:

fun transformation(input: String, findRegex: String, replaceRegex: String): String =
    input.replace(findRegex.toRegex(), replaceRegex)


fun main() {
    
    val input = "01121212"
    
    val findRegex = """(\d{3})(\d{3})(\d{3})(\d{2})"""

    val replaceRegex = """$1.$2.$3-$4"""
    
    val result = transformation(input, findRegex, replaceRegex)
    
    println(result)
}

https://pl.kotl.in/dPRrIMIVm

Полный код можно найти здесь: https://gitlab.com/pertence/masked-textinput.


person Augusto Pertence    schedule 16.07.2021    source источник
comment
Вы забыли использовать группы захвата, на которые ссылаются обратные ссылки.   -  person Wiktor Stribiżew    schedule 16.07.2021
comment
Этот ответ stackoverflow.com/a/37681441/4770439 работает и совпадает с моей первой попыткой, но я хочу, я хочу точки и тире, которые появляются, когда пользователь печатает.   -  person Augusto Pertence    schedule 16.07.2021
comment
Извините, регулярное выражение работает с обычным текстом. Когда пользователь печатает, есть некоторый код, который обрабатывает ввод и применяет регулярное выражение. Какой у вас код? Также см. Маска ввода не работает, когда значение удалено   -  person Wiktor Stribiżew    schedule 16.07.2021
comment
Я помещаю образец кода в вопрос. Я знаю, что есть другие вопросы о маскировании ввода с помощью Android Compose, но я хочу создать класс, которому не нужна пользовательская логика для каждого шаблона маски.   -  person Augusto Pertence    schedule 17.07.2021
comment
Вы не можете сделать его универсальным, потому что для каждого шаблона регулярного выражения вам понадобится конкретная замена. Примечание 01121212 не соответствует вашему образцу. 01121212000 будет соответствовать. Если вам нужно заменить частичные совпадения, вам понадобится callable в замене.   -  person Wiktor Stribiżew    schedule 17.07.2021
comment
Спасибо за помощь, но что означает callable? Можно ли использовать KCallable для реализации callable? kotlinlang.org/api/latest/jvm/stdlib/ kotlin.reflect/-k-вызываемый   -  person Augusto Pertence    schedule 17.07.2021
comment
Я думаю, вам нужно такое решение.   -  person Wiktor Stribiżew    schedule 17.07.2021


Ответы (1)


Вы можете использовать

fun transformation(input: String, findRegex: String, replaceRegex: String): String =
    input.replace("""\D+""".toRegex(), "").replace(findRegex.toRegex(), {
        it.groupValues[1].toString() + 
          (if (!it.groupValues[2].isNullOrEmpty()) ".${it.groupValues[2].toString()}"  else "") + 
          (if (!it.groupValues[3].isNullOrEmpty()) ".${it.groupValues[3].toString()}"  else "") + 
          (if (!it.groupValues[4].isNullOrEmpty()) "-${it.groupValues[4].toString()}"  else "")
    })
 
fun main(args: Array<String>) {
    val input = "0112121234" // 011.212.123-4
    // val input = "011" //  011
    // val input = "01121212" // 011.212.12
    // val input = "011212" // 011.212
    // val input = "01121" //  011.21
    // val input = "0112" //  011.2
    val findRegex = """^(\d{3})(\d{1,3})?(\d{1,3})?(\d{1,2})?$"""
    val replaceRegex = """$1.$2.$3-$4"""
    val result = transformation(input, findRegex, replaceRegex)
    println(result)
}

См. демонстрацию Kotlin в Интернете.

ПРИМЕЧАНИЯ:

  • .replace("""\D+""".toRegex(), "") - удаляет все нецифры
  • .replace(findRegex.toRegex(), { it.groupValues[1].toString() + (if (!it.groupValues[2].isNullOrEmpty()) ".${it.groupValues[2].toString()}" else "") + (if (!it.groupValues[3].isNullOrEmpty()) ".${it.groupValues[3].toString()}" else "") + (if (!it.groupValues[4].isNullOrEmpty()) "-${it.groupValues[4].toString()}" else "") }) — соответствует шаблону и заменяет совпадение разными заменами в зависимости от того, совпала группа или нет.

Регулярное выражение

^(\d{3})(\d{1,3})?(\d{1,3})?(\d{1,2})?$

См. демонстрацию регулярного выражения. Подробности:

  • ^ - начало строки
  • (\d{3}) - Группа 1: три цифры
  • (\d{1,3})? - необязательная группа 2, которая соответствует одной, двум или трем цифрам.
  • (\d{1,3})? - необязательная группа 3, которая соответствует одной, двум или трем цифрам
  • (\d{1,2})? - необязательная группа 4, которая соответствует одной или двум цифрам
  • $ - конец строки.
person Wiktor Stribiżew    schedule 18.07.2021