tags:

views:

315

answers:

5

Hi,

I have a seemingly simple problem though i am unable to get my head around it.

Let's say i have the following string: 'abcabcabcabc' and i want to get the last occurrence of 'ab'. Is there a way i can do this without looping through all the other 'ab's from the beginning of the string?

I read about anchoring the end of the string and then parsing the string with the required regular expression. I am unsure how to do this in Java (is it supported?).

Update: I guess i have caused a lot of confusion with my (over) simplified example. Let me try another one. Say, i have a string as thus - '12/08/2008 some_text 21/10/2008 some_more_text 15/12/2008 and_finally_some_more'. Here, i want the last date and hence i need to use regular expressions. I hope this is a better example.

Thanks, Anirudh

A: 
Pattern p = Pattern.compile("ab.*?$");
Matcher m = p.matcher("abcabcabcabc");
boolean b = m.matches();
chills42
A: 

I do not understand what you are trying to do. Why only the last if they are all the same? Why a regular expression and why not int pos = s.lastIndexOf(String str) ?

Jonas Elfström
Perhaps because ab is just an example? It could be [abc][abc] that you're looking for. Then lastIndexOf() is out. Of course, if it really is a simple string, then indeed lastIndexOf() is the answer.
PEZ
+2  A: 

This will give you the last date in group 1 of the match object.

.*(\d{2}/\d{2}/\d{4})
PEZ
Nice and simple solution. To alter that to his new conditions: .*(\d{2}/\d{2}/\d{4})
Gumbo
Thanks for alteration. I updated the answer with it.
PEZ
+1  A: 

Firstly, thanks for all the answers.

Here is what i tried and this worked for me:

Pattern pattern = Pattern.compile("(ab)(?!.*ab)");
Matcher matcher = pattern.matcher("abcabcabcd");
if(matcher.find()) {
  System.out.println(matcher.start() + ", " + matcher.end());
}

This displays the following:

6, 8

So, to generalize - <reg_ex>(?!.*<reg_ex>) should solve this problem where '?!' signifies that the string following it should not be present after the string that precedes '?!'.

Update: This page provides a more information on 'not followed by' using regex.

Anirudh
A: 

For the date example, you could do this with the Pattern API and not in the regex itself. The basic idea is to get all the matches, then return the last one.

public static void main(String[] args) {

    // this may be over-kill, you can replace with a much simpler but more lenient version
    final String dateRegex = "\\b(0?[1-9]|[12][0-9]|3[01])[- /.](0?[1-9]|1[012])[- /.](19|20)?[0-9]{2}\\b";
    final String sample = "12/08/2008 some_text 21/10/2008 some_more_text 15/12/2008 and_finally_some_more";

    List<String> allMatches = getAllMatches(dateRegex, sample);
    System.out.println(allMatches.get(allMatches.size() - 1));        
}

private static List<String> getAllMatches(final String regex, final String input) {

    final Matcher matcher = Pattern.compile(regex).matcher(input);
    return new ArrayList<String>() {{
        while (matcher.find())
            add(input.substring(matcher.start(), matcher.end()));
    }};
}
Chase Seibert
Yep, this works too. However, i was looking for something that would get me the answer without my looping over all the matches.
Anirudh