4

I want to search a string and mask the a credit card for security.

"Hi here is my card number its visa 4242 4242 4242 4242"
"Hi here is my card number its visa 4242424242424242"
"Hi here is my card number its visa 4242-4242-4242-4242"

Should be converted to:

"Hi here is my card number its visa **** **** **** 4242"

I need to do this on the client in Javascript. I know there are quite a few resources and questions on the web and SO.

I have found two regex, but both throw errors: "Uncaught SyntaxError: Invalid or unexpected token"

"Hi here is my card number its visa 4242 4242 4242 4242".match("(\d{4}-?){4}")

and

"Hi here is my card number its visa 4242 4242 4242 4242".match(\b4\d{3}[ -]?\d{4}[ -]?\d{4}[ -]?\d{4}[ -]\b)

I think the expressions are not compatible with JS?

I also understand they will return the string, I would then convert the string (mask it) and then use a simple replace on the original string.

Can anybody help me with the regex part of this problem?

MartinWebb
  • 1,998
  • 1
  • 13
  • 15
  • 1
    You should have a look at the syntax of regular expressions in javascript: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions – Denys Séguret Feb 02 '18 at 16:18
  • http://regex101.com – Neoares Feb 02 '18 at 16:24
  • Can someone explain why the Questions is down-voted. It seems to be harder and harder to ask anything on SO, can someone please explain where the question fails to meet approval? – MartinWebb Feb 02 '18 at 16:31
  • @MartinWebb I'm not sure either. The original issue you're having though is that `\d` is not valid. You need to escape ``\``. The second example would work other than you need to wrap your pattern in `/`. Also `[ -]\b` won't match anything in your case since `\b` matches positions between word characters and non-word characters (or start/end of line). I honestly think your question was downvoted for either 1. Not having used markdown (I edited your question to make it more legible) and/or 2. Because people *assume* everyone should know that you need to escape ``\`` or delimit a regex pattern – ctwheels Feb 02 '18 at 16:40
  • @MartinWebb I have no idea, but from experience you'll find more down votes on the questions about regex than most other questions on SO – KyleFairns Feb 02 '18 at 16:41
  • 1
    @KyleFairns I'll agree with you on that one. Wanna see a neat one? https://stackoverflow.com/questions/30791292/how-do-i-remove-a-style-element-from-an-inline-style-using-regex 68 downvotes. – ctwheels Feb 02 '18 at 16:42
  • @ctwheels Apologies for my lack of neatness. I will try and do better. Glad I asked appreciate the pointers. – MartinWebb Feb 02 '18 at 16:46
  • @MartinWebb no worries, it's tough when starting, but eventually you learn how to please most (you can never please everyone). You should also take a look at the [Help Center](https://stackoverflow.com/help). It has a lot of good information for SO (you can also get there by clicking on the `?` in the top right corner of the screen). – ctwheels Feb 02 '18 at 16:50
  • @ctwheels Starting I was programming in 1979. Now i feel really bad. New line of work? – MartinWebb Feb 02 '18 at 17:11
  • No, right line of work. Now, however, people seem to be more concerned with presentation rather than semantics. – ctwheels Feb 02 '18 at 17:18

2 Answers2

12

See regex in use here

\b(?:\d{4}[ -]?){3}(?=\d{4}\b)
  • \b Assert position as a word boundary. You can remove this if you want to catch cases such as My visa is1234567812345678
  • (?:\d{4}[ -]?){3} Match the following exactly 3 times
    • \d{4} Match any digit 4 times
    • [ -]? Optionally match a space or hyphen
  • (?=\d{4}\b) Positive lookahead ensuring what follows is 4 digits (and ensuring what follows it is not a word character). Similar to my first point, catching cards numbers that are followed by words such as My visa is 1234567812345678please use it carefully, use (?=\d{4}(?!\d)) instead.

const r = /\b(?:\d{4}[ -]?){3}(?=\d{4}\b)/gm
const a = [
  "Hi here is my card number its visa 4242 4242 4242 4242",
  "Hi here is my card number its visa 4242424242424242",
  "Hi here is my card number its visa 4242-4242-4242-4242"
]
const subst = `**** **** **** `

a.forEach(function(s) {
  console.log(s.replace(r, subst))
})
ctwheels
  • 21,901
  • 9
  • 42
  • 77
0

the regexp can be passed as a string ".." or regexp object /../. (when passed as string it is converted to RegExp object like with new RegExp("..")).

in first case the backslash must be doubled because of their special meaning between double quotes.

 "Hi here is my card number its visa 4242 4242 4242 4242".match("\\b(\\d{4}[- ]?){4}")

or

 "Hi here is my card number its visa 4242 4242 4242 4242".match(/\b(\d{4}[- ]?){4}/)
Nahuel Fouilleul
  • 18,726
  • 2
  • 31
  • 36