Mikhail
Mikhail

Reputation: 769

AND operator in regular expressions

I've searched for a while how to use logical operation AND in regular expressions in Java, and have failed.
I've tried to do as recommended in similar topic:

(?=match this expression)(?=match this too)(?=oh, and this)

and it doesn't work. Even simple examples with ?= returns false:

String b = "aaadcd";
System.out.println(b.matches("(?=aa.*)"));

Also I've read that (expression X)(expression Y) should work like X AND Y, but it works like X OR Y.
What am I doing wrong?

Added: Tried to add .* in the end. Still don't work.
For a example:

[2-9]?[0-9]{5,9}||1[2-9][0-9]{1,2}||120[0-9]{1,1}||119[0-9] = X - return false if number is less than 1190

[0-9]{1,3}||1[0-0][0-9]{1,2}||11[0-8][0-9]{1,1}||119[0-2] = Y - return false if number is greater than 1992.

String a = "1189";
a.matches(X) // return false
a.mathes(Y)  // return true
a.matches((?=X)(?=Y).*) // return true, but should return false.

Added: Yep, my regexp is not correct. My bad. The problem solved. Thank everyone very much!

Upvotes: 9

Views: 31971

Answers (3)

user85421
user85421

Reputation: 29670

I think what you need is (?=X)Y

  • (?=X) matches X, without consuming it (zero-width)
  • Y and matches Y

The main problem: X and Y are wrong, they should be (assuming 4 digits):

X: 119[0-9]|1[2-9][0-9]{2}|[2-9][0-9]{3}

  • 1190-1199, or
  • 1200-1999, or
  • 2000-9999

Y: 1[0-8][0-9]{2}|19[0-8][0-9]|199[0-2]

  • 1000-1899, or
  • 1900-1980, or
  • 1990-1992

Here a test code:

// X - return false if number is less than 1190
String X = "119[0-9]|1[2-9][0-9]{2}|[2-9][0-9]{3}"; 

// Y - return false if number is greater than 1992.
String Y = "1[0-8][0-9]{2}|19[0-8][0-9]|199[0-2]";

String pattern = "(?=" + X + ")" + Y;

String values = "1000 1100 1180 1189 1190 1191 1199 1200 1290 1900 1980 1989 " +
                "1990 1991 1992 1993 1999 2000 3000 2991 9999";
for (String string : values.split(" ")) {
    System.out.printf("\"%s\" %s%n", string, string.matches(pattern));
}

Upvotes: 12

morja
morja

Reputation: 8550

As Joachim answered, add a .* in the end:

String b = "aaadcd";
System.out.println(b.matches("(?=aaa)(?=.*dcd).*"));
// => true

String b = "aaaxxx";
System.out.println(b.matches("(?=aaa)(?=.*dcd).*"));
// => false

Upvotes: 1

Joachim Sauer
Joachim Sauer

Reputation: 308001

(?= does work.

What you're doing wrong is that you're using matches but your regex doesn't match anything.

(?= is a zero-width positive look-ahead: it doesn't "consume" any characters, but just verifies that its position is followed by something that matches its content.

So either replace your matches() call with Matcher.find() or make sure that your have something in your regex that matches the entire string (.* is a common candidate).

Upvotes: 7

Related Questions