I have this string :
var a='abc123#xyz123';
I want to build 2 regexes replace functions which :
1) Replace all characters that do have a future '#'
- with '*'
(not including '#')
so the result should look like :
'******#xyz123'
2) Replace all characters that do not have a future '#'
- with '*'
(not including '#')
so the result should look like :
'abc123#******'
What have I tried :
For the positive lookahead :
var a='abc123#xyz123';
alert(a.replace(/(.+(?=#))+/ig,'*')); //*#xyz123 --wrong result since it is greedy...
Question :
How can I make my regexes work as expected ?
I have this string :
var a='abc123#xyz123';
I want to build 2 regexes replace functions which :
1) Replace all characters that do have a future '#'
- with '*'
(not including '#')
so the result should look like :
'******#xyz123'
2) Replace all characters that do not have a future '#'
- with '*'
(not including '#')
so the result should look like :
'abc123#******'
What have I tried :
For the positive lookahead :
var a='abc123#xyz123';
alert(a.replace(/(.+(?=#))+/ig,'*')); //*#xyz123 --wrong result since it is greedy...
Question :
How can I make my regexes work as expected ?
Share Improve this question asked Oct 29, 2013 at 13:38 Royi NamirRoyi Namir 149k144 gold badges492 silver badges829 bronze badges 2-
In other words you want to replace all characters by
*
except#
? – Casimir et Hippolyte Commented Oct 29, 2013 at 13:42 - @CasimiretHippolyte According to future occurrence/non-occurrence of '#' using regex. yes. – Royi Namir Commented Oct 29, 2013 at 13:43
3 Answers
Reset to default 5First part using lookahead:
repl = a.replace(/.(?=[^#]*#)/g, "*");
//=> "******#xyz123"
Explanation:
This regex finds any character that is followed by #
using lookahead and replaced that with *
.
Second part using replace callback:
repla = a.replace(/#(.*)$/, function(m, t) { return m[0] + t.replace(/./g, '*'); } );
//=> abc123#******
Explanation:
This code finds text after #
. Inside the callback function is replaces every character with asterisk.
You can use indexOf
and substr
for this instead:
function maskBeforeAfter(before, str, character, maskCharacter) {
character = character || '#';
maskCharacter = maskCharacter || '*';
var characterPosition = str.indexOf(character);
if (characterPosition > -1) {
var mask = '';
if (before) {
for (var i = 0; i < characterPosition; i++) {
mask += maskCharacter;
}
return mask + str.substr(characterPosition);
} else {
for (var i = 0; i < str.length - characterPosition - 1; i++) {
mask += maskCharacter;
}
return str.substr(0, characterPosition + 1) + mask;
}
}
return str;
}
function maskBefore(str, character, maskCharacter) {
return maskBeforeAfter(true, str, character, maskCharacter);
}
function maskAfter(str, character, maskCharacter) {
return maskBeforeAfter(false, str, character, maskCharacter);
}
> var a = 'abc12345#xyz123';
> maskBefore(a);
"********#xyz123"
> maskAfter(a);
"abc12345#******"
If you insist on a simple regex:
The first one is already answered. The second can be written similarly:
a.replace(/[^#](?![^#]*#)/g, '*')
(?![^#]*#)
is a negative lookahead that checks that there isn't a pound after the current character.[^#]
also checks that the current character isn't a pound. (we could have also used/(?![^#]*#)./g
, but it is less pretty.
A positive option is:
a.replace(/[^#](?=[^#]*$)/g, '*');
- this is very similar to the first one:
(?=[^#]*$)
checks that we have only non-pounds ahead, until the end of the string.
In both of this options, all characters in strings with no pounds will be replaces: "abcd"
-> "****"