Java Matcher和Pattern:为什么会永远这样

时间:2010-12-02 12:39:19

标签: java regex

//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 个答案:

答案 0 :(得分:4)

我不知道你想要完成什么,但这里有一个错误:

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

您正在重新分配str,而匹配器仍然使用str的原始值。字符串是不可变的,如果您在一个位置重新分配变量,它不会更改另一个中的引用(请参阅{{3>}上的传递参考数据类型参数)。

还有一些更奇怪的事情发生,但也许我不能正确理解你。 您在评论中说字符串以ACCEPT开头并以#结尾。点即可。但这是你唯一要搜索的Pattern.compile("ACCEPT .*?\\.",Pattern.DOTALL);,而你也没有捕捉任何东西。那么为什么还要先寻找搜索呢?我以为你知道输入字符串是这样的。

您应该做的是发布一些示例输入以及要从中提取的数据。否则,没有人能够真正帮助你。


我现在在猜测:您似乎想从String中删除多个WITH子句。这应该更容易,像这样:

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但保留args),这是一个更新的解决方案:

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());

<强>输出:

  

接受意大利面配番茄,帕玛森芝士,橄榄凤尾鱼金枪鱼更多橄榄。