27

Example string: $${a},{s$${d}$$}$$

I'd like to match $${d}$$ first and replace it some text so the string would become $${a},{sd}$$, then $${a},{sd}$$ will be matched.

3
  • 2
    Couldn't you just use two separate regular expressions? Match #1 first, replace, and then try to match # 2? Commented Dec 11, 2010 at 0:10
  • @Pandincus: That would not allow nesting, otherwise yes. Commented Dec 11, 2010 at 0:17
  • For anyone coming here hoping to solve a recursive problem with regular expressions, something like pegjs.org may actually be more helpful. For instance, rules like var = "$${" name "}$$" would allow you to build a data structure that mimics the AST. At the end of the day, as simple as this is, it's truthfully a programming language, and don't be afraid to use the right tools for the job! Commented Apr 5, 2020 at 22:43

6 Answers 6

43

Annoyingly, JavaScript does not provide the PCRE recursive parameter (?R), so it is far from easy to deal with the nested issue. It can be done, however.

I won't reproduce code, but if you check out Steve Levithan's blog, he has some good articles on the subject. He should do, and he is probably the leading authority on regular expressions in JavaScript. He wrote XRegExp, which replaces most of the PCRE bits that are missing, and there is even a Match Recursive plugin!

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

7 Comments

I wouldn’t say that XRegExp replaces ‘most of the parts that are missing’, but it does help. For real regexes, though, you need full property and grapheme support. More than 80% of the web is Unicode now, and it’s a crime that you can’t cope with it in the browser.
@tchrist: The English-speaking world barely uses it, so it is therefore unimportant to the people who could change it. That added on to the principle of impossibly slow change in the base level of the web makes such things still a way off. Inconvenient to say the least.
@Orbling The English-speaking very much does use Unicode, and a great deal‼ See this analysis of one large English corpus. I’ve done others since then. Most web pages are in Unicode—you merely do not realize it. You cannot write English properly without it: no curly quotes, no £10 note, no 5¢ piece, &c&c. The web has seen a meteoric 800% growth in Unicode over the past 5 years. That is fast change, not slow‼ People aren’t paying attention, but Unicode is here nonetheless.
@tchrist: UTF8/16 are increasingly output as standard, because the webservers and editors are adopting it as default. Curly quotes are awful things anyhow, anathema to programmers. ;-)
@Orbling: No, UTF-8 only, not UTF-16. Nobody does webpages in UTF-16: that's dumb. UTF-16 has all the disadvantages of both UTF-8 and UTF-32, but enjoys none of the benefits of either. UTF-16 is a sorry legacy.
|
5

I wrote this myself:

String.prototype.replacerec = function (pattern, what) {
    var newstr = this.replace(pattern, what);
    if (newstr == this)
        return newstr;
    return newstr.replace(pattern, what);
};

Usage:

"My text".replacerec(/pattern/g,"what");

P.S: As suggested by lededje, when using this function in production it's good to have a limiting counter to avoid stack overflow.

5 Comments

I used it in a production code running for over an year. It a rare chance that a regex keeps on matching for infinite times. So no overflow! And that's a quick way to have recursive replace straight from JavaScript code.
The stack's limit is not infinity. IE6 can only handle 1130 calls. That's not 1130 regexp matches, it's total regexp matches plus whatever else you have going on. Saying this is a good enough answer is not correct because someone could be using it in an already function intensive environment, and something that shouldn't be adding to the stack could push it to overflow. so -1.
This can't recurse infinitely... there's no recursion?
I believe the line# 5 {return newstr.replace(pattern, what);} is supposed to be {return newstr.replacerec(pattern, what);} to obtain recursion. (add "rec" at the end of "replace"). Agree?
There's no need for recursion. <code> String.prototype.replacerec = function (pattern, what) { var prev = null; while (prev !== what) { prev = what; what = this.replace(pattern, what); } return what; }; </code>
0

Since you want to do this recursively, you are probably best off doing multiple matches using a loop.

Regex itself is not well suited for recursive-anything.

1 Comment

PCRE regex is decently suited for recursive patterns, it's just that Javascript doesn't have that capability, unfortunately.
0

You can try \$\${([^\$]*)}\$\$. The [^\$] means do not capture if a captured group contains $.

var re = new RegExp(/\$\${([^\$]*)}\$\$/, 'g'),
  original = '$${a},{s$${d}$$}$$',
  result = original.replace(re, "$1");

console.log('original: ' + original)
console.log('result: ' + result);

Comments

-1
var content = "your string content";
var found = true;
while (found) {
    found = false;
    content = content.replace(/regex/, () => { found = true; return "new value"; });
}

4 Comments

Although the concepts are perhaps there, there's so much that won't work, can go very wrong, and doesn't address the question asked.
What can go wrong? This simple pattern can solve the problem in the question with the right regex definition.
It has no fallback, so if it doesn't match, it will probably exceed memory allowance. Also what is "new value" and where should it come from? And you're not showing how OP's regex could actually work in this code.
You are wrong. If there is no more matched value 'found' stays false and the while loop exits. "new value" is the new value for matched string.
-2

In general, regular expressions are not well suited for that kind of problem. It's better to use a state machine.

3 Comments

@Pandincus: Nice, yacc for JS. :-)
Aye, a basic parser would be fine for this application.
Any links to examples of using a parser to recursively parse strings? I'm struggling to find anything.

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.