Java Matcher и Pattern: почему это продолжается вечно - PullRequest
0 голосов
/ 02 декабря 2010
//remove multiple with
       pat=Pattern.compile("ACCEPT .*?\\.",Pattern.DOTALL);
       m=pat.matcher(str);       
       while(m.find())
       {

          int start=m.group().indexOf("WITH") +1;
          String part=m.group().substring(start);
          part=part.replaceAll("WITH", "");
          part=m.group().substring(0, start).concat(part);

          if(!m.group().equals(part))
          {

              str=m.replaceFirst(part);

          }

       }

Есть идеи, почему это бесконечный цикл?m.group никогда не равно part.Я не знаю почему.Пробовал сброс, но ничего.

1 Ответ

4 голосов
/ 02 декабря 2010

Я понятия не имею, что вы пытаетесь выполнить, но здесь есть ошибка:

if(!m.group().equals(part))
{
    str=m.replaceFirst(part);
}

Вы переназначаете str, пока сопоставитель все еще работает с исходным значением str,Строки являются неизменяемыми, если вы переназначаете переменную в одном месте, она не меняет ссылку в другом (см. Передача аргументов типа ссылочного типа на на этой странице Sun java Tutorial ).

Происходят некоторые более странные вещи, но, возможно, я вас не правильно понимаю.В комментарии вы говорите, что строка начинается с ACCEPT и заканчивается на.точка .Но это единственное, что вы ищете Pattern.compile("ACCEPT .*?\\.",Pattern.DOTALL);, и вы тоже ничего не захватываете.Тогда зачем искать в первую очередь?Я думал, вы знали, что строки ввода такие.

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


Теперь я догадываюсь: вы, похоже, хотите удалить несколько предложений WITH из вашей String.Это должно быть намного проще, примерно так:

String test =
    "ACCEPT pasta "
       + "WITH tomatoes, parmesan cheese, olives "
       + "WITH anchovies WITH tuna WITH more olives.";

System.out.println(
    test.replaceAll(
        "(ACCEPT.*?WITH.*?)(?:\\s*WITH.*)(\\.)", "$1$2"
    )
);

Вывод:

ПРИНИМАТЬ макароны С помидорами, сыром пармезан, оливками.

Вот шаблон, объясненный:

(       // start a capturing group
ACCEPT  // search for the literal ACCEPT
.*?     // search for the shortest possible matching String
        // (so no other WITH can sneak in)
WITH    // search for the literal WITH
.*?     // search for the shortest possible matching String
        // (so no other WITH can sneak in)
)       // close the capturing group, we'll refer to this
        // group as $1 or matcher.group(1)
(?:     // start a non-capturing group
\\s*    // search for optional whitespace
WITH    // search for the literal WITH
.*      // search for anything, greedily
)       // close the group, we'll discard this one
(       // open another capturing group
\\.     // search for a single period
)       // close the group, the period is now accessible as $2

Учитывая ваши обновленные требования (удалите WITH, но оставьте аргументы) вот обновленное решение:

final Matcher matcher =
    Pattern.compile("WITH\\s*", Pattern.DOTALL).matcher(test);
final StringBuffer sb = new StringBuffer();
while(matcher.find()){
    matcher.appendReplacement(sb, sb.length() == 0
        ? matcher.group()
        : "");
}
matcher.appendTail(sb);
System.out.println(sb.toString());

Выход:

ПРИНЯТЬ макароны С помидорами, сыром пармезан, маслинами, анчоусами из тунца и оливками.

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