d-_-b
d-_-b

Reputation: 23191

Replace capture group of dynamic size

I want to replace the first part of regex for a URL with asterisks. Depending on the regex, for example:

Case 1

http://example.com/path1/path2?abcd => http://example.com/path1/**********

Regex 1: /^(https?:\/\/.+\/path1\/?)(.+)/but I want each character in group 2 to be replaced individually with *

or

Case 2

[email protected] => ******@example.com

Regex 2

/^(.+)(@.+)$/, similarly I want all characters in the first capture group to be replaced individually with *

I have tried to use capture groups, but then, I'm left with *@example.com

let email = `[email protected]`;
let regex = /^(.+)(@.+)$/;
console.log(email.replace(regex, '*$2'));

let url = `http://example.com/path1/path2?abcd`;
let regex = /^(https?:\/\/.+\/path1\/?)(.+)/;
console.log(url.replace(regex, '$1*'));

Upvotes: 2

Views: 995

Answers (2)

Casimir et Hippolyte
Casimir et Hippolyte

Reputation: 89574

You can use the sticky flag y (but Internet Explorer doesn't support it):

s = s.replace(/(^https?:\/\/.*?\/path1\/?|(?!^))./gy, '$1*')

But the simplest (and that is supported everywhere), is to use a function as replacement parameter.

s = s.replace(/^(https?:\/\/.+\/path1\/?)(.*)/, function (_, m1, m2) {
    return m1 + '*'.repeat(m2.length);
});

For the second case, you can simply check if there's an @ after the current position:

s = s.replace(/.(?=.*@)/g, '*');

Upvotes: 4

Wiktor Stribiżew
Wiktor Stribiżew

Reputation: 627087

You may use

let email = `[email protected]`;
let regex = /[^@]/gy;
console.log(email.replace(regex, '*'));

// OR
console.log(email.replace(/(.*)@/, function ($0,$1) { 
     return '*'.repeat($1.length) + "@";
}));

and

let url = `http://example.com/path1/path2?abcd`;
let regex = /^(https?:\/\/.+\/path1\/?)(.*)/gy;
console.log(url.replace(regex, (_,$1,$2) => `${$1}${'*'.repeat($2.length)}` ));
// OR
console.log(url.replace(regex, function (_,$1,$2) { 
     return $1 + ('*'.repeat($2.length)); 
}));

In case of .replace(/[^@]/gy, '*'), each char other than @ from the start of the string is replaced with * (so, up to the first @).

In case of .replace(/(.*)@/, function ($0,$1) { return '*'.repeat($1.length) + "@"; }), all chars up to the last @ are captured into Group 1 and then the match is replaced with the same amount of asterisks as the length of the Group 1 value + the @ char (it should be added into the replacement pattern as it is used as part of the consuming regex part).

The .replace(regex, (_,$1,$2) => `${$1}${'*'.repeat($2.length)}` ) follows the same logic as the case described above: you capture the part you need to replace, pass it into the anonymous callback method and manipulate its value using a bit of code.

Upvotes: 5

Related Questions