在Java中的字符串中间启动正则表达式匹配

时间:2010-08-01 17:32:18

标签: java regex

我正在使用regexps +一些手动解析在Java中解析一个相对复杂的表达式。我现在正在做的是删除我已经从字符串中解析的内容,所以我接下来要在字符串的开头解析。

我想改变这个,所以我有一个int pos变量,我不修改字符串。但是,PatternMatcher类似乎都没有标记要匹配的第一个字符的索引。有没有办法做到这一点?

(我知道我可以将str.substring(pos)传递给Matcher,但我想它会更昂贵,并且会使我的代码复杂化,因为我正在使用start()经常使用end()种方法。

6 个答案:

答案 0 :(得分:7)

java.util.regex.Matcher尝试在区域上找到匹配项,默认为整个输入,但可以显式设置为特定的子范围。

来自文档:

  

匹配器在其输入的子集中找到称为 region 的匹配项。默认情况下,该区域包含所有匹配器的输入。可以通过region(int start, int end)方法修改该区域,并通过regionStartregionEnd方法进行查询。可以更改区域边界与某些模式构造交互的方式。有关详细信息,请参阅useAnchoringBoundsuseTransparentBounds

请记住,与Java库类中的许多方法一样,start索引是包含,但end索引是独占


以下是一个示例用法:

    String text = "012 456 890 234";
    Pattern ddd = Pattern.compile("\\d{3}");
    Matcher m = ddd.matcher(text).region(3, 12);
    while (m.find()) {
        System.out.printf("[%s] [%d,%d)%n",
            m.group(),
            m.start(),
            m.end()
        );
    }

以上打印(as seen on ideone.com):

[456] [4,7)
[890] [8,11)

关于锚定边界和透明边界

如前所述,当您指定区域时,可以根据需要更改某些模式构造的行为。

锚定绑定使得该地区的边界与各种boundary matchers^$等匹配。

不透明边界基本上切断了前瞻,后瞻和某些边界匹配结构的其余输入。另一方面,在透明模式下,他们可以根据需要查看区域外的字符。

默认情况下,Matcher同时使用锚定不透明边界。这适用于大多数子区域匹配方案,但您可以根据需要设置自己的组合。

答案 1 :(得分:6)

答案 2 :(得分:1)

如何使用Matcher.region(int start, int end)

javadoc说:

设置此匹配器区域的限制。该区域是输入序列的一部分,将被搜索以查找匹配项。调用此方法会重置匹配器,然后将该区域设置为从start参数指定的索引处开始,并以end参数指定的索引结束。

答案 3 :(得分:1)

您正在寻找region()方法。每次匹配时,都会将区域的起始位置移动到匹配结束的位置。就Matcher而言,现在是输入的开始。

如果您设置了useAnchoringBounds()选项,则可以将区域的开头视为文本的开头(即^\A将匹配),如果你设置useTransparentBounds(),那么lookbehinds和单词边界仍然可以“看到”前面的文字。并且可以一次使用这两个选项。

如果您总是希望下一场比赛准确地从区域的开头开始,您甚至可以使用lookingAt()代替find() - 这是我用过的唯一一个很好用的方法。 ;)

答案 4 :(得分:0)

你的应用程序性能是否足够严重,str.substring(pos)是否重要?正则表达式将比子字符串慢几个数量级,因此不要让正则表达式更复杂,只需将其分解即可。那将是我的方法。

答案 5 :(得分:0)

String.substring是一个恒定时间操作;字符数据不会被复制,而是与原始字符串共享。从JDK源代码:

// Package private constructor which shares value array for speed.
String(int offset, int count, char value[]) {
this.value = value;
this.offset = offset;
this.count = count;
}

public String substring(int beginIndex, int endIndex) {
// error checking omitted
return ((beginIndex == 0) && (endIndex == count)) ? this :
    new String(offset + beginIndex, endIndex - beginIndex, value);
}

因此,在子串性能方面没有什么可担心的。