1

I need a regular expression that matches the second "abc" in "abcasdabchjkabc". I attempt to write code like this,

Pattern p = Pattern.compile("(?<=abc(.*?))abc");

but it throws a java.util.regex.PatternSyntaxException:

Look-behind group does not have an obvious maximum length near index 11
(?<=abc(.*?))abc
           ^
    at java.util.regex.Pattern.error(Pattern.java:1713)
    at java.util.regex.Pattern.group0(Pattern.java:2488)
    at java.util.regex.Pattern.sequence(Pattern.java:1806)
    at java.util.regex.Pattern.expr(Pattern.java:1752)
    at java.util.regex.Pattern.compile(Pattern.java:1460)
    at java.util.regex.Pattern.<init>(Pattern.java:1133)
    at java.util.regex.Pattern.compile(Pattern.java:823)

Please show me the right one!

Matt Ball
  • 354,903
  • 100
  • 647
  • 710
miaowhehe
  • 651
  • 1
  • 8
  • 11

3 Answers3

5

You cannot use * or + in a look-behind assertion.

Do you actually want to match everything in between the two abcs?

Pattern.compile("abc(.*?)abc");

Or do you just want to check that there are two abcs?

Pattern.compile("abc.*?abc");

I don't see a need for lookbehind in either case.

Community
  • 1
  • 1
Matt Ball
  • 354,903
  • 100
  • 647
  • 710
  • I know the way to match the whole string, and it's enough when I need to replace a string. I just try to match the second `"abc"` only, to see whether regular expression can do this. – miaowhehe Mar 13 '13 at 06:26
1

I guess you want something like:

java.util.regex.Pattern.compile("(?<=abc.{1,99})abc");

It finds the second abc.

jdb
  • 4,419
  • 21
  • 21
  • Yes! It's the one I'm looking for! Consider this string : `"abcabcdef"`, maybe `"(?<=abc.{0,99})abc"` is better. – miaowhehe Mar 13 '13 at 06:36
  • If that is what you want 0 will work. The main point is that you have to use the curly braces syntax in a look-behind. – jdb Mar 13 '13 at 06:40
  • 2
    This is very poor solution, you are assuming that the `abc` in the look-behind is at most 99 characters away from the `abc` that you want to match. – nhahtdh Mar 13 '13 at 07:59
1

A simple option is to match your pattern twice:

String input = "abcXYabcZRabc";

Pattern p = Pattern.compile("abc");
Matcher m = p.matcher(input);

m.find(); // what to do when there is no match?
m.find(); // what to do when there is only one match?

System.out.println("Second match is between " + m.start() + " and " + m.end());

Working example: http://ideone.com/uVZL3j

Kobi
  • 135,331
  • 41
  • 252
  • 292
  • This is also a nice approach. Thanks for telling me the usage of start() and end(). Just catch the `java.lang.IllegalStateException` if no match is available. – miaowhehe Mar 13 '13 at 06:46