0

I have the following that works perfectly with numbers but I don't know how to get it to work with letters too.

var word = "4556364607935616";

function mask() {
  if (word.length <= 4) {
    return word;
  } else {
    var masked =
      word.substring(0, word.length - 4).replace(/\d/g, "#") +
      word.substring(word.length - 4, word.length);
    return masked;
  }
}

I'm guessing \d targets numbers? I'm not sure where to look for a reference guide for this kind of thing. Any help would be much appreciated!

Penny Liu
  • 15,447
  • 5
  • 79
  • 98
leto
  • 489
  • 4
  • 18
  • [A reference guide for this kind of thing.](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions) – AuxTaco Feb 03 '18 at 00:02

5 Answers5

2

All you need to do is alter your regular expression slightly so that it works for letters as well. So, change /\d/g to /[a-z\d]/gi, where:

  • [a-z\d] matches a character in the range of a to z as well as numbers and
  • the i flag ensures that both lowercase and uppercase letters are matched.

Snippet:

var word = "4f563a46jy7u35616";

function mask() {
  if (word.length <=4) {
    return word
  } else {
    var masked = word.substring(0, word.length - 4).replace(/[a-z\d]/gi,"#") + 
    word.substring(word.length - 4, word.length)
    return masked;
  }
}

console.log(mask(word));
Angel Politis
  • 10,955
  • 14
  • 48
  • 66
  • Thanks a lot. It worked. I now know about the existence of the regex (I think it was touched on briefly on the beginner's course I'm doing) and so can now make sense of the symbols! – leto Feb 06 '18 at 17:55
  • That's great @mistarsv. I'm glad I could help! – Angel Politis Feb 06 '18 at 18:02
  • I did. My rep is too low though xD – leto Feb 06 '18 at 23:00
  • You can accept the answer by clicking the checkmark below the vote count @mistarsv. You probably attempted to vote and that's why it didn't let you – Angel Politis Feb 06 '18 at 23:10
1

The effective solution would be to not mask the string, but build a new string with provided length

var word = "4556364607935616";

function mask() {
  var LENGTH = 4
  var CHAR = '#'
  if (word.length <= LENGTH) {
    return word
  }
  var leftSideLength = word.length - LENGTH
  var result = ''
  while (leftSideLength--) result += CHAR
  return result + word.substring(word.length - 4, word.length)
}

Below the performance advantage shown

var word = "4556364607935616";

function maskNotRegex() {
  var LENGTH = 4
  var CHAR = '#'
  if (word.length <= LENGTH) {
    return word
  }
  var leftSideLength = word.length - LENGTH
  var result = ''
  while (leftSideLength--) result += CHAR
  return result + word.substring(word.length - 4, word.length)
}

// Credit: Angel Politis's anwer on this Post
function maskRegex() {
  if (word.length <= 4) {
    return word
  } else {
    var masked = word.substring(0, word.length - 4).replace(/[a-z\d]/gi, "#") +
      word.substring(word.length - 4, word.length)
    return masked;
  }
}

// Performance test
// Credit: https://stackoverflow.com/a/17943511/2308005

var iterations = 1000000;
console.time('Using regex');
for (var i = 0; i < iterations; i++) {
  maskRegex(word);
};
console.timeEnd('Using regex')

console.time('Not using regex');
for (var i = 0; i < iterations; i++) {
  maskNotRegex(word);
};
console.timeEnd('Not using regex')

To get more info about regex performance, read codinghorror post

Medet Tleukabiluly
  • 11,662
  • 3
  • 34
  • 69
1

RegExp Reference Guide with Tutorials: http://www.regular-expressions.info/

RegExp Playground: https://regexr.com/ (online tool to learn, build, & test regular expressions)

If you need to avoid replacing dashes - etc. use the word character \w (includes underscore):

var word="abc-364-079-5616", masked=word.replace(/\w/g, "#"); //[a-zA-Z0-9_]
if(word.length > 4) {
  masked = masked.substring(0, word.length-4) + word.substring(word.length-4);
} else {
  masked = word;
}
console.log(masked); // "###-###-###-5616"

Here's how masked changes in the last example:

  • masked = "###-###-###-####"
  • masked = "###-###-###-5616"

No RegExp Example

Here's an example that doesn't use regular expressions (masks any character):

var word = "abc6364607935616", masked = word; // word & masked are the same
if(word.length > 4) {
    masked = new Array(word.length - 4).join('#'); // create 4 less than word 
    masked += word.substring(word.length - 4); // add on 4 last characters
}
console.log(masked); // "###########5616"

Here's how masked changes in the last example:

  • masked = "abc6364607935616"
  • masked = "############"
  • masked = "############5616"
DJDaveMark
  • 2,669
  • 23
  • 35
  • Thanks! These are helpful links appreciate it. – leto Feb 06 '18 at 17:56
  • @mistarsv An upvote would be great if I helped. Also, have you decided on which answer helped you the most? – DJDaveMark Feb 06 '18 at 19:48
  • I'm new to this site so my up-votes don't show! I used Angel's as it was most similar to mine. The others went a little too in depth for my purposes at the moment. – leto Feb 06 '18 at 22:59
0

This is the shortest I got. You can use Regex pattern (\w(?=\w{4})) to mask the last 4 letters like so:

let word = "4f563a46jy7u35616";

function mask() {
  if (word.length <= 4) {
    return word;
  } else {
    return word.replace(/\w(?=\w{4})/g, "#");
  }
}

console.log(mask(word));
Penny Liu
  • 15,447
  • 5
  • 79
  • 98
0

If you want to show only end of the string and mask the remaining part, you could use this solution:

Input : "1234567890"

Output : #####67890

const str = '1234567890'

const maskString = (string = '', maskCharacter = '#') => {
  const maskLength = string.length <= 10 ? string.length / 2 : string.length - 5
  return Array(Math.round(maskLength)).fill(maskCharacter).join('') + string.substring(maskLength)
}

console.log(maskString(str))
NIKHIL C M
  • 3,873
  • 2
  • 28
  • 35