Удаление любого символа в строке с помощью Java regex

У меня есть эта проблема домашней работы, где я должен использовать regex для удаления любого символа в строке.

В одной части я должен удалить символы в индексе 1,3,5... Я сделал это следующим образом:

String s = "1a2b3c4d5";
System.out.println(s.replaceAll("(.).", "$1"));

Это печатает 12345 который является тем, что я хочу. По существу я соответствую двум символам за один раз, и заменяющий первым символом. Я использовал получение группы, чтобы сделать это.

Проблема, я испытываю затруднения из-за второй части домашней работы, где я должен удалить символы в индексе 0,2,4...

Я сделал следующее:

String s = "1a2b3c4d5";
System.out.println(s.replaceAll(".(.)", "$1"));

Это печатает abcd5, но корректный ответ должен быть abcd. Мой regex является только неправильным, если длина входной строки нечетна. Если это даже, то мой regex хорошо работает.

Я думаю, что я действительно близко к ответу, но я не уверен, как зафиксировать его.

9
задан Bill the Lizard 20 September 2012 в 12:42
поделиться

3 ответа

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

String s = "1a2b3c4d5";
System.out.println(s.replaceAll(".(.)?", "$1"));
// prints "abcd"

Это работает, потому что:

  • Регулярное выражение по умолчанию является жадным, оно будет принимать второй символ, если он есть
    • Если ввод имеет нечетную длину, второй символ не будет там при последней замене, но вы все равно сопоставите один символ (т.е. последний символ во вводе)
  • Вы все равно можете использовать обратные ссылки при замене, даже если группа не соответствует
    • Будет подставлена ​​пустая строка, а не «null»
    • Это отличается от Matcher.group (int) , который возвращает null для неудачных групп

Ссылки


Более пристальный взгляд на первую часть

Давайте рассмотрим Посмотрите внимательнее на первую часть домашнего задания:

String s = "1a2b3c4d5";
System.out.println(s.replaceAll("(.).", "$1"));
// prints "12345"

Здесь вам не нужно было использовать ? для второго символа, но он «работает», потому что даже если вы не сопоставили последний символ, вам не нужно было! Последний символ может оставаться незаменимым из-за спецификации проблемы.

Теперь предположим, что мы хотим удалить символы с индексом 1,3,5 ... и поместить символы с индексом 0,2,4 ... в скобки.

String s = "1a2b3c4d5";
System.out.println(s.replaceAll("(.).", "($1)"));
// prints "(1)(2)(3)(4)5"

А-ха !! Теперь вы испытываете ту же проблему с вводом нечетной длины! Вы не можете сопоставить последний символ с вашим регулярным выражением, потому что вашему регулярному выражению нужно два символа, но в конце есть только один символ для ввода нечетной длины!

Решение, опять же, состоит в том, чтобы сделать сопоставление второго символа необязательным:

String s = "1a2b3c4d5";
System.out.println(s.replaceAll("(.).?", "($1)"));
// prints "(1)(2)(3)(4)(5)"
19
ответ дан 4 December 2019 в 10:03
поделиться

мое регулярное выражение неверно только в том случае, если длина входной строки нечетная. если это даже, то мое регулярное выражение работает нормально.

Измените выражение на . (.)? - вопросительный знак делает второй символ необязательным, что означает, что не имеет значения, четный или нечетный ввод

2
ответ дан 4 December 2019 в 10:03
поделиться

Регулярному выражению требуется 2 символа для сопоставления, поэтому последний символ не работает.

Это регулярное выражение:

".(.{0,1})"

сделает второй символ необязательным, поэтому он также будет соответствовать вашей последней цифре «5»

0
ответ дан 4 December 2019 в 10:03
поделиться
Другие вопросы по тегам:

Похожие вопросы: