Выбор первых X цифр в строке и замена каждой цифры символом

Я пытаюсь заменить все цифры в строке на *.

Прямо сейчас у меня есть это

val regex = "^[\\d+].{8}"
val pattern = Pattern.compile(regex)
code = code.replace(pattern.toRegex(), "*** *** *")

Вроде работает, но я хочу * вместо "*** *** *" поэтому идея состоит в том, чтобы заменить отдельные цифры вместо блока.

пример строки:

123 456 789 0

Возможно, я вас неправильно понял, но если вы хотите заменить только один, есть replaceFirst. Кроме того, ваше текущее регулярное выражение соответствует любому количеству цифр, за которым следует любой символ 8 раз. Если вы хотите заменить только цифры, вам нужно добавить группу захвата, чтобы исключить остальные. т.е. """^\d*(.{8})""" заменено на *$1"

Zoe 20.03.2019 17:21

Я хочу заменить каждое вхождение цифры на *, пока я не заменю 8 цифр, моя окончательная строка должна выглядеть как «*** *** *89 0»

Thought 20.03.2019 17:30

А если цифр меньше 8?

Wiktor Stribiżew 20.03.2019 17:40

Строка всегда будет иметь один и тот же размер

Thought 20.03.2019 17:41

Однако в примере вы не заменяете 8 цифр, вы заменяете только 7. В любом случае, (0 until 7).forEach { raw = raw.replaceFirst("\\d".toRegex(), "*") } значительно менее подвержен ошибкам и также поддерживает разные форматы. И может быть немного быстрее. К сожалению, метод замены в настоящее время не имеет счетчика. Я не могу придумать какое-либо регулярное выражение, которое делает это точно, когда оно включает пробелы, без замены полного счета вручную. Но если стиль строки всегда один и тот же, просто "*** *** *" + rex.substring(9).

Zoe 20.03.2019 17:46
1
5
1 704
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Вместо регулярного выражения вы, вероятно, просто захотите повторить n количество раз, пока не замените нужное количество символов. Используя функциональный подход, вы можете сделать что-то вроде:

fun String.redact(numDigits:Int = 8): String {
    val charArray = toCharArray()

    charArray.withIndex()
        .filter { (_, char) -> Character.isDigit(char) }
        .take(numDigits)
        .forEach { (index, _) -> charArray[index] = '*' }

    return String(charArray)
}

Потом:

println("123 456 789 0".redact()) // *** *** **9 0
Ответ принят как подходящий

Читаемый подход регулярного выражения состоит в том, чтобы сопоставить любое количество символов от начала строки до 8-й цифры, а затем передать совпадение в блок и заменить второй раз цифровым шаблоном:

val s = "123 456 789 0"
val regex = """^(?:\D*\d){8}""".toRegex()
println(s.replace(regex) { it.value.replace(Regex("""\d"""), "*") })
// => *** *** **9 0

См. Демонстрация Котлина онлайн

Регулярное выражение ^(?:\D*\d){8} соответствует

  • ^ - начало строки
  • (?:\D*\d){8} - 8 повторений:
    • \D* - 0 или более символов кроме цифр
    • \d - цифра.

Просто к вашему сведению, вы можете добиться того же с жестко запрограммированной версией с восемью группами захвата, s.replace("""^(\D*)\d(\D*)\d(\D*)\d(\D*)\d(\D*)\d(\D*)\d(\D*)\d(\D*)\d""".toRegex(), "$1*$2*$3*$4*$5*$6*$7*$8*") если у вас всегда есть 8 цифр во входной строке.

Другие вопросы по теме