Удаление всех остальных символов в строке с помощью регулярного выражения Java - PullRequest
9 голосов
/ 02 июля 2010

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

В одной части я должен удалить символы с индексом 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. Мое регулярное выражение неверно, только если длина входной строки нечетная. Если это даже, то мое регулярное выражение работает нормально.

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

Ответы [ 3 ]

19 голосов
/ 02 июля 2010

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

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

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

  • Regex по умолчанию жадный, он будетвозьмите второй символ, если он есть
    • Когда ввод имеет нечетную длину, второй символ не будет присутствовать при последней замене, но вы все равно будете соответствовать одному символу (то есть последнему символу на входе)
  • Вы все еще можете использовать обратные ссылки при замене, даже если группа не соответствует
    • Она будет подставлена ​​в пустую строку, а не "null"
    • Thisотличается от 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)"
2 голосов
/ 02 июля 2010

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

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

0 голосов
/ 02 июля 2010

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

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

".(.{0,1})"

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...