101

You can backreference like this in JavaScript:

var str = "123 $test 123";
str = str.replace(/(\$)([a-z]+)/gi, "$2");

This would (quite silly) replace "$test" with "test". But imagine I'd like to pass the resulting string of $2 into a function, which returns another value. I tried doing this, but instead of getting the string "test", I get "$2". Is there a way to achieve this?

// Instead of getting "$2" passed into somefunc, I want "test"
// (i.e. the result of the regex)
str = str.replace(/(\$)([a-z]+)/gi, somefunc("$2"));

5 Answers 5

124

Like this:

str.replace(regex, function(match, $1, $2, offset, original) { return someFunc($2); })
Sign up to request clarification or add additional context in comments.

3 Comments

Awesome, where can I find more info about this?
Cool. To clarify: $1 and $2 are user-chosen parameter names here (chosen to mimic the backreference symbols); the - varying! - number of these parameters corresponds to the number of capture groups in the regex.
40

Pass a function as the second argument to replace:

str = str.replace(/(\$)([a-z]+)/gi, myReplace);

function myReplace(str, group1, group2) {
    return "+" + group2 + "+";
}

This capability has been around since Javascript 1.3, according to mozilla.org.

1 Comment

+1 for readability. Also as it's 2024: const myReplace = ( str, group1, group2 ) => "+" + group2 + "+"
1

Using ESNext, quite a dummy links replacer but just to show-case how it works :

let text = 'Visit http://lovecats.com/new-posts/ and https://lovedogs.com/best-dogs NOW !';

text = text.replace(/(https?:\/\/[^ ]+)/g, (match, link) => {
  // remove ending slash if there is one
  link = link.replace(/\/?$/, '');
  
  return `<a href="${link}" target="_blank">${link.substr(link.lastIndexOf('/') +1)}</a>`;
});

document.body.innerHTML = text;

Comments

0

Note: Previous answer was missing some code. It's now fixed + example.


I needed something a bit more flexible for a regex replace to decode the unicode in my incoming JSON data:

var text = "some string with an encoded '&#115;' in it";

text.replace(/&#(\d+);/g, function() {
  return String.fromCharCode(arguments[1]);
});

// "some string with an encoded 's' in it"

Comments

0

If you would have a variable amount of backreferences then the argument count (and places) are also variable. The MDN Web Docs describe the follwing syntax for sepcifing a function as replacement argument:

function replacer(match[, p1[, p2[, p...]]], offset, string)

For instance, take these regular expressions:

var searches = [
    'test([1-3]){1,3}',  // 1 backreference
    '([Ss]ome) ([A-z]+) chars',  // 2 backreferences
    '([Mm][a@]ny) ([Mm][0o]r[3e]) ([Ww][0o]rd[5s])'  // 3 backreferences
];
for (var i in searches) {
    "Some string chars and many m0re w0rds in this test123".replace(
        new RegExp(
            searches[i]
            function(...args) {
                var match = args[0];
                var backrefs = args.slice(1, args.length - 2);
                // will be: ['Some', 'string'], ['many', 'm0re', 'w0rds'], ['123']
                var offset = args[args.length - 2];
                var string = args[args.length - 1];
            }
        )
    );
}

You can't use 'arguments' variable here because it's of type Arguments and no of type Array so it doesn't have a slice() method.

Comments

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.