1

I just found that positive look behind doesn't work in older browsers and i'm stuck with this issue on IE11 i.e. Unexpected quantifier

regex: /(?<=\d{4})\d(?=\d{4})/g

input: const string = 4444333322221111;

string.replace(/(?<=\d{4})\d(?=\d{4})/g, "#");

expected outcome: 4444########1111

any alternative for this regex would be helpful.

Community
  • 1
  • 1
Asad Shah
  • 771
  • 2
  • 8
  • 22
  • 1
    const string = 4444333322221111; – Asad Shah Apr 19 '20 at 20:34
  • 1
    do you have only digits? – Nina Scholz Apr 19 '20 at 20:41
  • Your input string looks like a payment card number. You don't need regex, you can use simple string processing functions like [`String.substring()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/substring) and string concatenation. – axiac Apr 19 '20 at 20:42
  • 1
    @Nina yes only digits. – Asad Shah Apr 19 '20 at 20:43
  • @axiac currently im using substring to over come this issue.. but i wanted to know the best possible alternative for this regex. – Asad Shah Apr 19 '20 at 20:45
  • 1
    `String.substring()` seems better than regex to me. The code is easier to understand (and it could also be faster but this is probably not your concern.) – axiac Apr 19 '20 at 20:49
  • 1
    Asad, when asked for clarification it is generally best to edit your question rather than elaborating in comments. Questions should be self-contained and readers should not be expected to read all comments to understand what is being asked. – Cary Swoveland Apr 19 '20 at 23:04

3 Answers3

0

If your string only consists of digits you really need no regex, all you need is a couple of string manipulation methods:

// Adapted from https://stackoverflow.com/a/5450113/3832970, count will always be positive here
function strRepeat(pattern, count) {
    var result = '';
    while (count > 1) {
        if (count & 1) result += pattern;
        count >>= 1, pattern += pattern;
    }
    return result + pattern;
};

var string = "4444333322221111";
console.log(
    string.substring(0,4) + strRepeat("#", string.length-8) + string.slice(-4)
)

If you need to mask digits enclosed with four digits on either side in a longer string you may use:

function strRepeat(pattern, count) {
    var result = '';
    while (count > 1) {
        if (count & 1) result += pattern;
        count >>= 1, pattern += pattern;
    }
    return result + pattern;
};

var string = "111109876543210000 abc 1234012345678904321";
console.log(
  string.replace(/\d{9,}/g, function(match) { 
     return match.substr(0,4) + strRepeat("#", match.length-8) + match.slice(-4); 
  })
)

Here,

  • /\d{9,}/g matches all occurrences of nine or more digits
  • function(match) {...} - a callback method that takes the regex match and you may manipulate the output here
  • match.substr(0,4) + "#".repeat(match.length-8) + match.slice(-4) - concats the first 4 digits, then the digits that need to be replaced with # are appended, and then the remaining 4 digits are added.

If you want, you may make the regex pattern with capturing groups, it will make the callback method a bit smaller, but will make the regex longer:

function strRepeat(pattern, count) {
    var result = '';
    while (count > 1) {
        if (count & 1) result += pattern;
        count >>= 1, pattern += pattern;
    }
    return result + pattern;
};

var string = "111109876543210000 abc 1234012345678904321";
console.log(
  string.replace(/(\d{4})(\d+)(\d{4})/g, function($0, $1, $2, $3) { 
     return $1 + strRepeat("#", $2.length-8) + $3; 
  })
)

Here, the (\d{4})(\d+)(\d{4}) pattern will capture 4 digits into Group 1 ($1), then 1+ digits will be captured into Group 2 ($2) and then 4 digits will be captured into Group 3 ($3).

Wiktor Stribiżew
  • 607,720
  • 39
  • 448
  • 563
-1

You could take a function and the index and replace either with digit for the first four digits or with #.

var string = '4444333322221111';

console.log(string.replace(/\d(?=\d{4})/g, function (v, i) { return i < 4 ? v : '#'; }));

Update with sliced strings.

var string = '4444333322221111',
    result =
        string.slice(0, 4) +
        string.slice(4, -4).replace(/./g, '#') +
        string.slice(-4);

console.log(result)
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
-1

Your input string looks like a payment card number. You don't need regex, you can use simple string processing functions like String.substring() and string concatenation.

For example:

const str = '1111222233334444';
const masked = str.substring(0, 4) + 
   '#'.repeat(str.length - 8) + 
   str.substring(str.length - 4)
console.log(masked);

A regex solution doesn't need to use lookups:

const str = '1111222233334444';
const masked = str.replace(/^(\d{4})(\d*)(\d{4})$/,
  `$1${"#".repeat(str.length - 8)}$3`);
console.log(masked);
axiac
  • 68,258
  • 9
  • 99
  • 134