7

第一次发帖。

首先,我知道如何同时使用模式匹配器和字符串拆分。我的问题是哪个最适合我在我的示例中使用,为什么?或提出更好的替代方案的建议。

任务:我需要在未知字符串中的两个已知正则表达式之间提取未知名词。

我的解决方案:获取名词的开头和结尾(来自 Regexp 1&2)和子字符串以提取名词。

String line = "unknownXoooXNOUNXccccccXunknown";
int goal = 12 ;
String regexp1 = "Xo+X";
String regexp2 = "Xc+X";
  1. 我需要在第一个正则表达式之后找到索引位置。
  2. 我需要在第二个正则表达式之前找到索引位置。

A)我可以使用模式匹配器

    Pattern p = Pattern.compile(regexp1);
    Matcher m = p.matcher(line);
    if (m.find()) {
        int afterRegex1 = m.end();
    } else {
        throw new IllegalArgumentException();
        //TODO Exception Management;
    }

B)我可以使用字符串拆分

    String[] split = line.split(regex1,2);
    if (split.length != 2) {
        throw new UnsupportedOperationException();
        //TODO Exception Management;
    }
    int afterRegex1 = line.indexOf(split[1]);

我应该使用哪种方法,为什么?我不知道哪个在时间和内存上更有效。两者都足够接近我自己的可读性。

4

4 回答 4

5

我会这样做:

String line = "unknownXoooXNOUNXccccccXunknown";
String regex = "Xo+X(.*?)Xc+X";

Pattern p = Pattern.compile(regex);
Matcher m = p.matcher(line);
if (m.find()) {
   String noun = m.group(1);
}

(.*?)用于使名词不情愿的内部匹配。这可以防止我们的结尾模式再次出现在字符串的未知部分中。

编辑

这是有效的,因为(.*?)定义了一个捕获组。模式中只定义了一个这样的组,因此它的索引为 1( 的参数m.group(1))。这些组从 1 开始从左到右进行索引。如果模式是这样定义的

String regex = "(Xo+X)(.*?)(Xc+X)";

然后会有三个捕获组,这样

m.group(1); // yields "XoooX"
m.group(2); // yields "NOUN"
m.group(3); // yields "XccccccX"

一个组 0,但它匹配整个模式,它相当于这个

m.group(); // yields "XoooXNOUNXccccccX"

有关您可以使用 做什么的更多信息Matcher,包括在源字符串中获取模式的开始和结束位置的方法,请参阅Matcher JavaDocs

于 2013-10-16T17:34:06.953 回答
3

String.split()除非您处于紧密循环中,否则您应该使用可读性。

Persplit()的 javadocsplit()相当于 ,如果你在一个紧密的循环中,Pattern.compile()你可以优化掉它。

于 2013-10-16T17:31:11.187 回答
2

看起来您想要获得一个独特的事件。为此,只需

input.replaceAll(".*Xo+X(.*)Xc+X.*", "$1")

为了效率,请Pattern.matcher(input).replaceAll改用。

如果您输入的内容包含换行符,请使用Pattern.DOTALLs修饰符。


如果您想使用拆分,请考虑使用 Guava 的Splitter. 它表现得更理智,也接受有Pattern利于速度的 a。

于 2013-10-16T17:36:15.287 回答
0

如果你真的需要这些位置,你可以这样做:

String line = "unknownXoooXNOUNXccccccXunknown";
String regexp1 = "Xo+X";
String regexp2 = "Xc+X";

Matcher m=Pattern.compile(regexp1).matcher(line);
if(m.find())
{
  int start=m.end();
  if(m.usePattern(Pattern.compile(regexp2)).find())
  {
    final int end = m.start();
    System.out.println("from "+start+" to "+end+" is "+line.substring(start, end));
  }
}

但如果你只需要介于两者之间的词,我推荐 Ian McLaird 所展示的方式。

于 2013-10-16T17:38:44.333 回答