Find the last match with Java regex matcher

后端 未结 11 2068
情书的邮戳
情书的邮戳 2020-12-01 14:27

I\'m trying to get the last result of a match without having to cycle through .find()

Here\'s my code:

String in = \"num 123 num 1 num 698 num 19238          


        
相关标签:
11条回答
  • 2020-12-01 14:43

    Compared to the currently accepted answer, this one does not blindly discard elements of the list using the".*" prefix. Instead, it uses "(element delimiter)*(element)" to pick out the last element using .group(2). See the function magic_last in code below.

    To demonstrate the benefit of this approach I have also included a function to pick out the n-th element which is robust enough to accept a list that has fewer than n elements. See the function magic in code below.

    Filtering out the "num " text and only getting the number is left as an exercise for the reader (just add an extra group around the digits pattern: ([0-9]+) and pick out group 4 instead of group 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));
        }
      }
    
    }
    

    Output:

    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
    
    0 讨论(0)
  • 2020-12-01 14:44
    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);
    }
    
    0 讨论(0)
  • 2020-12-01 14:46

    Java patterns are greedy by default, the following should do it.

        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 ));
        }
    
    0 讨论(0)
  • 2020-12-01 14:46

    Use negative lookahead:

    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);
    }
    

    The regular expression reads as "num followed by one space and at least one digit without any (num followed by one space and at least one digit) at any point after it".

    You can get even fancier by combining it with positive lookbehind:

    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();
    }
    

    That one reads as "at least one digit preceded by (num and one space) and not followed by (num followed by one space and at least one digit) at any point after it". That way you don't have to mess with grouping and worry about the potential IndexOutOfBoundsException thrown from Matcher.group(int).

    0 讨论(0)
  • 2020-12-01 14:48

    just use \Z - end of string mach

    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);
    }
    
    0 讨论(0)
  • 2020-12-01 14:52

    Regular expressions are greedy:

    Matcher m=Pattern.compile(".*num '([0-9]+) ",Pattern.DOTALL).matcher("num 123 num 1 num 698 num 19238 num 2134");
    

    will give you a Matcher for the last match, and you can apply it to most regexes by prepending ".*". Of course, if you can't use DOTALL, you might want to use (?:\d|\D) or something similar as your wildcard.

    0 讨论(0)
提交回复
热议问题