Regex to find credit card numbers?

Can you help me with a regex pattern that finds the below:

Visa:
1. A string that starts with the number "4" and is either:
  A. Followed by 15 integers and then a non-integer.
  B. Followed by a pattern like this "4000-0000-0000-0000" where the dash can be any ASCII printable character other than a number and the zeros can be any integer.

MasterCard:
1. A string that starts with the numbers "51" or 52 or 53 or 54 or 55 and is either:
  A. Followed by 15 integers and then a non-integer.
  B. Followed by a pattern like this "5100-0000-0000-0000" where the dash can be any ASCII character other than a number and the zeros can be any integer.

American Express:
1. A string that starts with the numbers 34 or 37 and is either:
  A. Followed by 14 integers and then a non-integer.
  B. Followed by a pattern like this "3400-000000-00000" where the dash can be any ASCII printable character other than a number and the zeros can be any integer.

Discover Card:
1. A string that starts with the numbers 60 or 62 or 64 or 65 and is either:
  A. Followed by 14 integers and then a non-integer.
  B.  Followed by a pattern like this "6200-0000-0000-0000" where the dash can be any ASCII printable character other than a number and the zeros can be any integer.

http://en.wikipedia.org/wiki/Bank_card_number

PS. Have to have a "non-integer after the 16 digit integer string" so that long number strings like 123412344345634523453245234532453245 are not returned.  We're looking for text like this, "I was talking with a customer about their order and they gave me their new credit card number of 4567-8901-2345-6789 because the old one didn't work but the system was offline right before lunch so I wrote their credit card number here in this note where my manager told me not to."
Geoff MillikanAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

tdlewisCommented:
Try this:
/(^|\D)((4\d|5[12345]|6[0245])\d\d\D?\d\d\d\d\D?\d\d\d\d\D?\d\d\d\d|3[47]\d\d\D?\d\d\d\d\d\d\D?\d\d\d\d\d)(\D|$)/
0
VishnukumarCommented:
Simplified format of the above

/(^|\D)((4\d|5[12345]|6[0245])\d{2}\D?\d{4}D?\d{4}D?\d{4}|3[47]\d{2}\D?\d{6}\D?\d{4})(\D|$)/
0
tdlewisCommented:
Not quite. It would be:

/(^|\D)((4\d|5[12345]|6[0245])\d{2}\D?\d{4}D?\d{4}D?\d{4}|3[47]\d{2}\D?\d{6}\D?\d{5})(\D|$)/
0
Cloud Class® Course: Python 3 Fundamentals

This course will teach participants about installing and configuring Python, syntax, importing, statements, types, strings, booleans, files, lists, tuples, comprehensions, functions, and classes.

Geoff MillikanAuthor Commented:
Rats.  I ran these and just found out the tool we're using, Windows Grep 2.3, doesn't support \D and pipe, etc - it only support the below regular expression characters.  Dang.  Sorry about that - could you re-write with just these? (Windows just doesn't have very powerful file system searching tools like Linux so Windows Grep seems to be one of the few solutions.)

^ Circumflex - Constrain to start of line
$ Dollar - Constrain to end of line
. Period - Match any character
* Asterisk - Match 0 or more
+ Plus - Match 1 or more
? Question mark - Optionally match
() Brackets - Expression group
[ ] Square brackets - Character group
\ Backslash - Quote next character
0
Geoff MillikanAuthor Commented:
WinGrep supports only the below regular expression characters....
ScreenShot014.png
0
tdlewisCommented:
Without the pipe you're going to need a LOT of regular expressions to replicate that single regular expression and to satisfy your requirements.

You could get by with four regular expressions if you removed this requirement:

Have to have a "non-integer after the 16 digit integer string" so that long number strings like 123412344345634523453245234532453245 are not returned.

That requirement is why the regular expression includes these bits:
/(^|\D)...(\D|$)/

That says to match the beginning of the string OR anything that's not a digit, (the ellipsis removes the part that matches a credit card number), followed by anything that's not a digit or the end of the string.

To get just that behavior you need for variations:
/^...[^0-9]?/
/[^0-9]?...[^[0-9]?/
/^...$/
/[^0-9]?...$/

To eliminate the pipe in the inner part, you need four regular expressions (one for each card number). That means you will need a total of sixteen regular expressions to satisfy all of your requirements.
0
tdlewisCommented:
Here are the four credit card expressions:
/4\d{3}[^0-9]?\d{4}[^0-9]?\d{4}[^0-9]?\d{4}/
/5[12345]\d{2}[^0-9]?\d{4}[^0-9]?\d{4}[^0-9]?\d{4}/
/6[0245])\d{2}[^0-9]?\d{4}[^0-9]?\d{4}[^0-9]?\d{4}/
/3[47]\d{2}[^0-9]?\d{6}[^0-9]?\d{5}/

(By the way, the version that Vishnukumar posted was broken. I fixed all the places where that version replace \D with just D.)

Finally, here are the sixteen regular expressions that cover all your cases:
/^4\d{3}[^0-9]?\d{4}[^0-9]?\d{4}[^0-9]?\d{4}[^0-9]?/
/[^0-9]?4\d{3}[^0-9]?\d{4}[^0-9]?\d{4}[^0-9]?\d{4}[^[0-9]?/
/^4\d{3}[^0-9]?\d{4}[^0-9]?\d{4}[^0-9]?\d{4}$/
/[^0-9]?4\d{3}[^0-9]?\d{4}[^0-9]?\d{4}[^0-9]?\d{4}$/

/^5[12345]\d{2}[^0-9]?\d{4}[^0-9]?\d{4}[^0-9]?\d{4}[^0-9]?/
/[^0-9]?5[12345]\d{2}[^0-9]?\d{4}[^0-9]?\d{4}[^0-9]?\d{4}[^[0-9]?/
/^5[12345]\d{2}[^0-9]?\d{4}[^0-9]?\d{4}[^0-9]?\d{4}$/
/[^0-9]?5[12345]\d{2}[^0-9]?\d{4}[^0-9]?\d{4}[^0-9]?\d{4}$/

/^6[0245])\d{2}[^0-9]?\d{4}[^0-9]?\d{4}[^0-9]?\d{4}[^0-9]?/
/[^0-9]?6[0245])\d{2}[^0-9]?\d{4}[^0-9]?\d{4}[^0-9]?\d{4}[^[0-9]?/
/^6[0245])\d{2}[^0-9]?\d{4}[^0-9]?\d{4}[^0-9]?\d{4}$/
/[^0-9]?6[0245])\d{2}[^0-9]?\d{4}[^0-9]?\d{4}[^0-9]?\d{4}$/

/^3[47]\d{2}[^0-9]?\d{6}[^0-9]?\d{5}[^0-9]?/
/[^0-9]?3[47]\d{2}[^0-9]?\d{6}[^0-9]?\d{5}[^[0-9]?/
/^3[47]\d{2}[^0-9]?\d{6}[^0-9]?\d{5}$/
/[^0-9]?3[47]\d{2}[^0-9]?\d{6}[^0-9]?\d{5}$/
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
Geoff MillikanAuthor Commented:
Ugh, ok.  Well, we need that requirement.  And from the screenshot above - the pipe is supported!  So I took out the \d and the \D and filled in just really basic parameters (the character before the credit card number has to be a space, the character between the groups of four numbers has to be either a space or a dash, etc) to see if I could get it to find the credit card number in the below text string.  No luck.  What am I missing?

/(^|[ ])((4[0-9]|5[12345]|6[0245])[0-9]{2}[0-9]?[0-9]{4}[- ]?[0-9]{4}[- ]?[0-9]{4}|3[47][0-9]{2}[0-9]?[0-9]{6}[0-9]?[0-9]{5})([0-9]|$)/

#Text string to search
I was talking with a customer about their order and they gave me their new credit card number of 4567-8901-2345-6789 because the old one didn't work but the system was off-line right before lunch so I wrote their credit card number here in this note where my manager told me not to.

Open in new window

0
Geoff MillikanAuthor Commented:
<rant>Why can't Windows just work like Linux?  How is it that Windows has such a big market share without professional-grade file system search ability?</rant>
0
tdlewisCommented:
Here it is without \d or \D:

/(^|[^0-9])((4[0-9]|5[12345]|6[0245])[0-9]{2}[^0-9]?[0-9]{4}[^0-9]?[0-9]{4}[^0-9]?[0-9]{4}|3[47][0-9]{2}[^0-9]?[0-9]{6}[^0-9]?[0-9]{5})([^0-9]|$)/
0
tdlewisCommented:
FYI:
\d is the same as [0-9]
\D is the same as [^0-9]
0
Geoff MillikanAuthor Commented:
Holy cow, you are the regex wizard.
0
Geoff MillikanAuthor Commented:
Good answer, thank you!
0
Geoff MillikanAuthor Commented:
Using the below regex in the Effective File Search (http://www.sowsoft.com/search.htm)::

(^|[^0-9])((4[0-9]|5[12345]|6[0245])[0-9]{2}[^0-9]?[0-9]{4}[^0-9]?[0-9]{4}[^0-9]?[0-9]{4}|3[47][0-9]{2}[^0-9]?[0-9]{6}[^0-9]?[0-9]{5})([^0-9]|$)

Finds the credit card number in this text string:

"I was talking with a customer about their order and they gave me their new credit card number of 4567-8901-2345-6789 because the old one didn't work but the system was off-line right before lunch so I wrote their credit card number here in this note where my manager told me not to."
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Regular Expressions

From novice to tech pro — start learning today.