在java中的字符串中间开始ReGeXP匹配
我正在使用regexps+一些手动解析在Java中解析一个相对复杂的表达式。我现在正在做的是从字符串中删除我已经解析过的内容,所以我接下来要在字符串的开头进行解析 我想更改它,因此我有一个在java中的字符串中间开始ReGeXP匹配,java,regex,Java,Regex,我正在使用regexps+一些手动解析在Java中解析一个相对复杂的表达式。我现在正在做的是从字符串中删除我已经解析过的内容,所以我接下来要在字符串的开头进行解析 我想更改它,因此我有一个int pos变量,并且不修改字符串。但是,模式和匹配器类似乎都没有标记要匹配的第一个字符的索引。有什么办法吗 (我知道我可以将str.substring(pos)传递给Matcher,但我想这会更昂贵,并且会使我的代码复杂一点,因为我经常使用start()和end()方法)。你的应用程序性能是否足够关键,st
int pos
变量,并且不修改字符串。但是,模式
和匹配器
类似乎都没有标记要匹配的第一个字符的索引。有什么办法吗
(我知道我可以将
str.substring(pos)
传递给Matcher
,但我想这会更昂贵,并且会使我的代码复杂一点,因为我经常使用start()
和end()
方法)。你的应用程序性能是否足够关键,str.substring(pos)是否重要?正则表达式将比子字符串慢多个数量级,因此与其使正则表达式更复杂,不如将其分解。这就是我的方法。对你很有用使用
javadoc说:
设置此匹配器区域的限制。区域是将被搜索以查找匹配项的输入序列的一部分。调用此方法将重置匹配器,然后将区域设置为从start参数指定的索引开始,到end参数指定的索引结束 A尝试在区域上查找匹配项,该区域默认为整个输入,但可以显式设置为特定子范围
从文件中:
匹配器在称为区域的输入子集中查找匹配项。默认情况下,区域包含匹配器的所有输入。区域可以通过方法修改,也可以通过和方法查询。区域边界与某些图案构造交互的方式可以更改。有关更多详细信息,请参阅和
请记住,与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()
);
}
以上打印内容():
关于锚定界和透明界 如前所述,指定区域时,可以根据需要更改某些模式构造的行为 锚定边界使区域的边界匹配各种(
^
,$
等)
不透明边界本质上切断了lookaheads、lookbehinds和某些边界匹配构造的其余输入。另一方面,在透明模式下,他们可以根据需要看到区域外的字符
默认情况下,
Matcher
同时使用锚定边界和不透明边界。这适用于大多数子区域匹配场景,但您可以根据需要设置自己的组合。字符串。子字符串是一个固定时间操作;字符数据不会被复制,而是与原始字符串共享。从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);
}
因此,就子字符串性能而言,无需担心任何问题。该方法正是您所需要的。每次匹配某个对象时,都会将该区域的起始位置向上移动到该匹配结束的位置。就匹配器而言,这就是输入的开始
如果设置该选项,则可以将区域的开头视为文本的开头(即,^
或\A
将在此处匹配),如果设置,则向后看和单词边界仍可以“查看”前面的文本。您可以同时使用这两个选项
如果您总是希望下一个匹配精确地从区域的开始处开始,您甚至可以使用而不是--这是我发现的唯一一个适合该方法的用法。;) 这是true
关于substring
是O(1)
时间和空间,但是索引需要重新编号以转换回全局索引,这是一个麻烦和容易出错的问题。谢谢,看起来这正是我需要的。我想在问之前我应该好好看看。naikus/Polygene的答案也很合适,但我不需要太多的控制。谢谢À注释如果有人有相同的问题:使用find()
,^
字符匹配整个字符串的开头,而不是搜索的开头。要确保匹配字符串的开头,请使用region().lookingAt()
(解释如下)。
// 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);
}