2

As a follow up to this question (not by me), I need to replace leading numbers of an id with \\3n (where n is the number we're replacing).

Some examples:

"1foo"    -> "\\31foo"
"1foo1"   -> "\\31foo1"
"12foo"   -> "\\31\\32foo"
"12fo3o4" -> "\\31\\32fo3o4"
"foo123"  -> "foo123"

Below is a solution that replaces every instance of the number, but I don't know enough regex to make it stop once it hits a non-number.

function magic (str) {
    return str.replace(/([0-9])/g, "\\3$1");
}

... Or is regex a bad way to go? I guess it would be easy enough to do it, just looping over each character of the string manually.

5
  • can you post your expected out Commented Aug 26, 2015 at 10:38
  • 1
    @Raghavendra I think I did. After the arrow in the examples is the expected output. Commented Aug 26, 2015 at 10:39
  • I think you need to use a reverse string approach here and use a look-ahead. Commented Aug 26, 2015 at 10:41
  • you can do like this '123fo3o4'.split(/(\d+)/) in my opinion Commented Aug 26, 2015 at 10:53
  • @Raghavendra and then run through the first one with numbers, replace each with the backslash string and put it all together? It could work, yes. But then I think I'd rather just use a regular for ... of loop to traverse the string and break out once we hit a non-digit. Commented Aug 26, 2015 at 10:55

3 Answers 3

4

Here is a way to achieve what you need using a reverse string + look-ahead approach:

function revStr(str) {
    return str.split('').reverse().join('');
}

var s = "12fo3o4";
document.write(revStr(revStr(s).replace(/\d(?=\d*$)/g, function (m) {
    return m + "3\\\\";
 }))
);

The regex is matching a number that can be followed by 0 or more numbers only until the end (which is actually start) of a reversed string (with \d(?=\d*$)). The callback allows to manipulate the match (we just add reversed \\ and 3. Then, we just reverse the result.

Sign up to request clarification or add additional context in comments.

Comments

4

Just use two steps: first find the prefix, then operate on its characters:

s.replace(/^\d+/, function (m) {
    return [].map.call(m, function (c) {
        return '\\3' + c;
    }).join('');
});

No need to emulate any features.

3 Comments

yes nice one. got new one today, missed to see the replace api
This won't work in old browsers (like IE8), otherwise, a nice one. Still, it also performs split and join. I also think you need to use \\\\3 to get actually \\3 in the replacement string.
The \\ vs \\\\ part is moot for me personally, but actually the browser support isn't. Thanks for pointing that out.
2

Here is how I would have done it:

function replace(str) {
    var re = /^([\d]*)/;
    var match = str.match(re)[0];        
    var replaced = match.replace(/([\d])/g, "\\3$1");        
    str = str.replace(match, replaced);
    return str;
}

document.write(replace("12fo3o4"));

Don't get me wrong: the other answers are fine! My focus was more on readability.

1 Comment

Good solution, and you don't even need the if test.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.