13

What I want to do is str.replace(pattern, callback),

not simply str.replace(pattern, replace_pattern),

is it possible to do it in javascript?

wamp
  • 5,789
  • 17
  • 52
  • 82
  • Here is an example: http://stackoverflow.com/questions/2966172/censoring-selected-words-replacing-them-with-using-a-single-replaceall/2966273#2966273 – Amarghosh Jun 04 '10 at 03:55

3 Answers3

22

Why, yes, you can do exactly that: str.replace(pattern, function () { ... }).

Here's some documentation: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace#specifying_a_function_as_the_replacement

Steve Chambers
  • 37,270
  • 24
  • 156
  • 208
deceze
  • 510,633
  • 85
  • 743
  • 889
  • 1
    Hi, seems good but not solves in the case of `g` regex: no ["array group" here](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace#Specifying_a_function_as_a_parameter) at guide... How to supply the function with the arbitrary array of `RegExp('\{([^\}]*)\}', 'g')`? (imagine the case of URI-template resolution by regex). – Peter Krauss Jul 24 '20 at 14:44
7

Yes

var s2 = s1.replace(/regex/, function(whole, part1, part2, ...) { ... })

The function is passed the whole matched string as the first argument. If there are any capturing groups, those are passed as subsequent arguments.

Pointy
  • 405,095
  • 59
  • 585
  • 614
  • But how to get the full array for an arbitrary set of parts? – Peter Krauss Jul 24 '20 at 06:21
  • @PeterKrauss as in any function, the complete set of actual parameters passed are available in the `arguments` array-like object. – Pointy Jul 24 '20 at 11:33
  • No ["array group" here](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace#Specifying_a_function_as_a_parameter) , the last are `offset` and `string`, and you need an a prioru knowledge about number of matched itens. Look, I am talking about `g` option in a regular expression... Example `RegExp('\{([^\}]*)\}', 'g')` for an URI template string. – Peter Krauss Jul 24 '20 at 14:39
  • OK, well I guess you're out of luck. – Pointy Jul 25 '20 at 12:06
  • thanks, check my loop solution [below](https://stackoverflow.com/a/63108491/287948) – Peter Krauss Jul 27 '20 at 04:00
0

The general case have no solution with s1.replace(/regex/, function(whole, part1, part2, ...partN) { ... }), where you need to know all parts and it is not valid g option;

arbitrary number of itens

The example of RegExp('\{([^\}]*)\}', 'g') can be solved by a loop... Supposing the URI-template problem, replacing each placeholder by global getData dictionary.

const tpl = 'myEtc/{aa}/etc1/{bb}/etc2'
const getData = {"aa":"expandAA","bb":"expandBB"}

function expandTpl(getData,s0){  // s0 is the link_template_input
  const r = RegExp('\{([^\}]*)\}', 'g');
  let s = '';
  let idx=0
  for (let a; (a=r.exec(s0)) !== null;) {
    s   += ( s0.substring(idx, r.lastIndex-a[0].length) + getData[a[1]] )
    idx = r.lastIndex
  }
  if ( idx<s0.length ) s += s0.substring(idx,s0.length)
  return s
}

console.log( tpl )
console.log( expandTpl(getData,tpl) )
Peter Krauss
  • 13,174
  • 24
  • 167
  • 304