我试图获得匹配的最后结果,而不必循环通过.find()
这是我的代码:
String in = "num 123 num 1 num 698 num 19238 num 2134";
Pattern p = Pattern.compile("num '([0-9]+) ");
Matcher m = p.matcher(in);
if (m.find()) {
in = m.group(1);
}
这将给我第一个结果。我怎样才能找到最后一场比赛,而不是通过一个潜在的巨大名单?
答案 0 :(得分:17)
您可以将.*
添加到正则表达式中,greedily将使用截至上一场比赛的所有字符:
import java.util.regex.*;
class Test {
public static void main (String[] args) {
String in = "num 123 num 1 num 698 num 19238 num 2134";
Pattern p = Pattern.compile(".*num ([0-9]+)");
Matcher m = p.matcher(in);
if(m.find()) {
System.out.println(m.group(1));
}
}
}
打印:
2134
您也可以反转字符串以及更改正则表达式以匹配反向字符串:
import java.util.regex.*;
class Test {
public static void main (String[] args) {
String in = "num 123 num 1 num 698 num 19238 num 2134";
Pattern p = Pattern.compile("([0-9]+) mun");
Matcher m = p.matcher(new StringBuilder(in).reverse());
if(m.find()) {
System.out.println(new StringBuilder(m.group(1)).reverse());
}
}
}
但两种解决方案都不比使用while (m.find())
,IMO。
答案 1 :(得分:14)
要获得最后一场比赛,即使这样也有效,并且不确定为什么之前没有提到过这个:
String in = "num 123 num 1 num 698 num 19238 num 2134";
Pattern p = Pattern.compile("num '([0-9]+) ");
Matcher m = p.matcher(in);
if (m.find()) {
in= m.group(m.groupCount());
}
答案 2 :(得分:5)
为什么不保持简单?
in.replaceAll(".*[^\\d](\\d+).*", "$1")
答案 3 :(得分:3)
Java没有提供这样的机制。我唯一可以建议的是对最后一个索引的二进制搜索。
这将是这样的:
N = haystack.length();
if ( matcher.find(N/2) ) {
recursively try right side
else
recursively try left side
这是代码,因为我发现这是一个有趣的问题:
import org.junit.Test;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import static org.junit.Assert.assertEquals;
public class RecursiveFind {
@Test
public void testFindLastIndexOf() {
assertEquals(0, findLastIndexOf("abcdddddd", "abc"));
assertEquals(1, findLastIndexOf("dabcdddddd", "abc"));
assertEquals(4, findLastIndexOf("aaaaabc", "abc"));
assertEquals(4, findLastIndexOf("aaaaabc", "a+b"));
assertEquals(6, findLastIndexOf("aabcaaabc", "a+b"));
assertEquals(2, findLastIndexOf("abcde", "c"));
assertEquals(2, findLastIndexOf("abcdef", "c"));
assertEquals(2, findLastIndexOf("abcd", "c"));
}
public static int findLastIndexOf(String haystack, String needle) {
return findLastIndexOf(0, haystack.length(), Pattern.compile(needle).matcher(haystack));
}
private static int findLastIndexOf(int start, int end, Matcher m) {
if ( start > end ) {
return -1;
}
int pivot = ((end-start) / 2) + start;
if ( m.find(pivot) ) {
//recurse on right side
return findLastIndexOfRecurse(end, m);
} else if (m.find(start)) {
//recurse on left side
return findLastIndexOfRecurse(pivot, m);
} else {
//not found at all between start and end
return -1;
}
}
private static int findLastIndexOfRecurse(int end, Matcher m) {
int foundIndex = m.start();
int recurseIndex = findLastIndexOf(foundIndex + 1, end, m);
if ( recurseIndex == -1 ) {
return foundIndex;
} else {
return recurseIndex;
}
}
}
我还没有找到破解测试用例。
答案 4 :(得分:2)
默认情况下,Java模式是贪婪的,以下应该这样做。
String in = "num 123 num 1 num 698 num 19238 num 2134";
Pattern p = Pattern.compile( ".*num ([0-9]+).*$" );
Matcher m = p.matcher( in );
if ( m.matches() )
{
System.out.println( m.group( 1 ));
}
答案 5 :(得分:2)
使用否定前瞻:
String in = "num 123 num 1 num 698 num 19238 num 2134";
Pattern p = Pattern.compile("num (\\d+)(?!.*num \\d+)");
Matcher m = p.matcher(in);
if (m.find()) {
in= m.group(1);
}
正则表达式在"之后的任何点读取为" num后跟一个空格和至少一个没有任何数字(num后跟一个空格和至少一个数字)的数字。
通过将其与积极的观察结合起来,你可以变得更加漂亮:
String in = "num 123 num 1 num 698 num 19238 num 2134";
Pattern p = Pattern.compile("(?<=num )\\d+(?!.*num \\d+)");
Matcher m = p.matcher(in);
if (m.find()) {
in = m.group();
}
那个读取为&#34;至少一个数字前面带有(num和一个空格),并且在&#34;之后的任何点都没有跟着(num后跟一个空格和至少一个数字)。
这样你就不必混淆分组并担心IndexOutOfBoundsException
引发的潜在Matcher.group(int)
。
答案 6 :(得分:1)
String in = "num 123 num 1 num 698 num 19238 num 2134";
Pattern p = Pattern.compile("num '([0-9]+) ");
Matcher m = p.matcher(in);
String result = "";
while (m.find())
{
result = m.group(1);
}
答案 7 :(得分:0)
正则表达式是贪婪的:
Matcher m=Pattern.compile(".*num '([0-9]+) ",Pattern.DOTALL).matcher("num 123 num 1 num 698 num 19238 num 2134");
会为最后一场比赛提供Matcher
,您可以通过添加“。*”将其应用于大多数正则表达式。当然,如果您无法使用DOTALL
,则可能需要使用(?:\d|\D)
或类似通配符的内容。
答案 8 :(得分:0)
这似乎是一种更合理的方法。
public class LastMatchTest {
public static void main(String[] args) throws Exception {
String target = "num 123 num 1 num 698 num 19238 num 2134";
Pattern regex = Pattern.compile("(?:.*?num.*?(\\d+))+");
Matcher regexMatcher = regex.matcher(target);
if (regexMatcher.find()) {
System.out.println(regexMatcher.group(1));
}
}
}
.*?
是一个不情愿的匹配,所以它不会吞噬一切。 ?:
强制非捕获组,因此内部组是组1.以贪婪的方式匹配多个使得它在整个字符串中匹配,直到所有匹配都用尽,使组1具有您最后一个匹配的值。
答案 9 :(得分:0)
与当前接受的答案相比,此答案不会使用".*"
前缀盲目地丢弃列表中的元素。相反,它使用"(element delimiter)*(element)"
使用.group(2)
选出最后一个元素。请参阅以下代码中的函数magic_last
。
为了证明这种方法的好处,我还提供了一个函数来挑选第n个元素,该元素足够强大,可以接受少于n个元素的列表。请参阅以下代码中的函数magic
。
过滤掉“num”文本,只留下数字作为读者的练习(只需在数字模式周围添加一个额外的组:([0-9]+)
并选择组4而不是组2)。
package com.example;
import static java.lang.System.out;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Foo {
public static void main (String [] args) {
String element = "num [0-9]+";
String delimiter = ", ";
String input;
input = "here is a num bro: num 001; hope you like it";
magic_last(input, element, delimiter);
magic(1, input, element, delimiter);
magic(2, input, element, delimiter);
magic(3, input, element, delimiter);
input = "here are some nums bro: num 001, num 002, num 003, num 004, num 005, num 006; hope you like them";
magic_last(input, element, delimiter);
magic(1, input, element, delimiter);
magic(2, input, element, delimiter);
magic(3, input, element, delimiter);
magic(4, input, element, delimiter);
magic(5, input, element, delimiter);
magic(6, input, element, delimiter);
magic(7, input, element, delimiter);
magic(8, input, element, delimiter);
}
public static void magic_last (String input, String element, String delimiter) {
String regexp = "(" + element + delimiter + ")*(" + element + ")";
Pattern pattern = Pattern.compile(regexp);
Matcher matcher = pattern.matcher(input);
if (matcher.find()) {
out.println(matcher.group(2));
}
}
public static void magic (int n, String input, String element, String delimiter) {
String regexp = "(" + element + delimiter + "){0," + (n - 1) + "}(" + element + ")(" + delimiter + element + ")*";
Pattern pattern = Pattern.compile(regexp);
Matcher matcher = pattern.matcher(input);
if (matcher.find()) {
out.println(matcher.group(2));
}
}
}
输出:
num 001
num 001
num 001
num 001
num 006
num 001
num 002
num 003
num 004
num 005
num 006
num 006
num 006
答案 10 :(得分:0)
只需使用\ Z-字符串马赫数的结尾
String in = "num 123 num 1 num 698 num 19238 num 2134";
Pattern p = Pattern.compile("num ([0-9]+)\\Z");
Matcher m = p.matcher(in);
if (m.find()) {
in = m.group(1);
}