第一次发帖。
首先我知道如何同时使用Pattern Matcher&字符串拆分。 我的问题最适合我在我的例子中使用,为什么? 或建议更好的替代方案。
任务: 我需要在未知字符串中的两个已知正则表达式之间提取未知的NOUN。
我的解决方案: 获取名词的开头和结尾(来自Regexp 1& 2)和子串来提取名词。
String line = "unknownXoooXNOUNXccccccXunknown";
int goal = 12 ;
String regexp1 = "Xo+X";
String regexp2 = "Xc+X";
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
String[] split = line.split(regex1,2);
if (split.length != 2) {
throw new UnsupportedOperationException();
//TODO Exception Management;
}
int afterRegex1 = line.indexOf(split[1]);
我应该使用哪种方法?为什么? 我不知道哪个在时间和记忆上更有效率。 两者都足够接近我自己。
答案 0 :(得分: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);
}
(.*?)
用于在NOUN 不情愿上进行内部匹配。这可以保护我们免受我们的结束模式再次出现在字符串的未知部分的情况。
修改强>
这是有效的,因为(.*?)
定义了捕获组。在模式中只定义了一个这样的组,因此它获得索引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
答案 1 :(得分:3)
除非你处于紧张的循环中,否则你应该使用String.split()
来提高可读性。
根据split()
's javadoc,split()
相当于Pattern.compile()
,如果你处于紧张的循环中,你可以优化它。
答案 2 :(得分:2)
看起来你想要得到一个独特的事件。为此,只需
input.replaceAll(".*Xo+X(.*)Xc+X.*", "$1")
为提高效率,请改用Pattern.matcher(input).replaceAll
。
如果您输入包含换行符,请使用Pattern.DOTALL
或s
修饰符。
如果您想使用拆分,请考虑使用Guava的Splitter
。它表现得更加清醒,也接受Pattern
,这对速度有利。
答案 3 :(得分: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所展示的方式。