0

I am trying to write code that returns a credit card vendor using regular expression, which seem to work, eg:

// Visa - always begins digit 4, 13 or 16 digits long
^[4].{12}|^[4].{15} 

// Visa Electron - begin with the code pattern, 16 digits long
4026.{12}|417500.{10}|4405.{12}|4508.{12}|4844.{12}|4913.{12}|4917.{12}

So for a method isVisa I want the regex to say "return Visa based on the Visa regex, but not Visa Electron"

This code does not work:

    public static String isVisa(String number) {
    Pattern p = Pattern.compile("^[4].{12}|^[4].{15}&&(!4026.{12}|!417500.{10}|!4405.{12}|!4508.{12}|!4844.{12}|!4913.{12}|!4917.{12})");
    Matcher m = p.matcher(number);
    if (m.matches()) return "Visa";
    else return "";
}
3
  • FYI You need length 16-19 and Visa overlaps Eletcron in many ranges, to do this properly you need a regularly updated lookup table of BIN ranges (I was doing something similar last week) Commented Jun 21, 2014 at 15:29
  • Wouldn't the last line be better for return m.matches() ? "Visa" : ""; Commented Jun 21, 2014 at 15:29
  • 1
    This seems like a boolean function to me. You might want to return a boolean here instead of a string Commented Jun 21, 2014 at 15:39

3 Answers 3

1

The matches() method validates the regular expression against the entire string, so you do not need the start ^ and end $ anchors. Also the regular expression engine is matching these characters &! as literals, which it seems you are trying to use them as operators.

To ignore those patterns you can use a Negative Lookahead to achieve this.

(?!.*(?:(?:4026|4405|4508|4844|4913|4917).{12}|417500.{10}))(?=4.{12}|4.{15}).*

Example: This returns true for the first two since the rest are not valid for your case.

String[] numbers = { "4000236512341234", "4000222213232222", "4026122222222222", 
                     "4175000000000000", "4405343434344343", "4508111111111111",
                     "4844000000000000", "4913000000000000", "4917000000000000" };

Pattern p = Pattern.compile("(?!.*(?:(?:4026|4405|4508|4844|4913|4917).{12}|417500.{10}))(?=4.{12}|4.{15}).*");

for (String x: numbers) {
    Matcher m = p.matcher(x);
    System.out.println(m.matches());
}

Output:

true
true
false
false
false
false
false
false
false
Sign up to request clarification or add additional context in comments.

Comments

0

Use positive and negative lookaheads to check for the lines which starts with some numbers and doesn't starts with some specific numbers.

^(?!417500.{10}|4026.{12}|4405.{12}|4508.{12}|4844.{12}|4913.{12}|4917.{12})(?=4.{12}|4.{15}).*

DEMO

Comments

0

You could use a very simple and easy to understand regex:

4026.{12}|417500.{10}|4405.{12}|4508.{12}|4844.{12}|4913.{12}|4917.{12}|([4].{12}|[4].{15})

This will match all the Visa Electron patterns without capturing anything. When you get a match, check capture group one isn't null for it to be Visa.

See this answer for a great explanation of the technique.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.