0

I have this string

{ prop1: 'val1', prop2:{ prop3: 'val3' ,  messages: {something:'val'}  messages: { something:'val2', x : {x : 1, y : 5} } } , prop4: 'val4' }

how can I find all instances of messages: { ... } in javascript with xregexp (or another solution)

This /messages: (\{(?>[^{}]+|(?1))*\})/g is working in php, but not in javascript

enter image description here

Also couldn't figure it out by using xregexp recursion http://xregexp.com/api/#matchRecursive

Tried https://repl.it/@RezaRahmati/xregexp

XRegExp.matchRecursive(str, 'messages: {', '}', 'gi')

but getting Unbalanced delimiter found in string error

Update

as @vs97 and @barmar comment, I tried messages: (\{.+\}) and works on multiline, still issue when it's single line

enter image description here

Reza
  • 18,865
  • 13
  • 88
  • 163
  • *maybe as simple as this?* messages: (\{.+\}) https://regex101.com/r/Fs4SAq/1 – vs97 Sep 06 '19 at 00:57
  • Are the messages on different lines as in regex101.com, or a single line as in the question? – Barmar Sep 06 '19 at 01:00
  • [Javascript doesn't natively support recursive regex](https://stackoverflow.com/a/4414453/8237835) but you might be able to use a [library that does](https://www.npmjs.com/package/xregexp). Otherwise, I'd say you should make/use a simple parser as this JSON-like structure doesn't look like a regular language. Especially if your format doesn't rely on white space to separate the lines and only the `{}` are important. – Khauri Sep 06 '19 at 01:01
  • 1
    @Khauri The question says he tried to use that library. – Barmar Sep 06 '19 at 01:01
  • I can't read. But in that case I think it'd be nice to see the code for what OP tried. – Khauri Sep 06 '19 at 01:04
  • @vs97 thanks, although it works in regex101 but in my code result is not correct ` str = str.replace(/messages: (\{.+\})/gm, 'x'); console.log(str);` and result is `{ prop1: 'val1', prop2:{ prop3: 'val3' , x` which last `}` is missing – Reza Sep 06 '19 at 01:06
  • @Barmar right now on multiple lines – Reza Sep 06 '19 at 01:12
  • `.+` shouldn't match across line breaks. – Barmar Sep 06 '19 at 01:14
  • That test has the messages object on the same line as the last `}`, which is why it's removing it. But if they're on lines by themselves the suggested regexp should work. – Barmar Sep 06 '19 at 01:16
  • @Barmar yes it works on multiline, what about single line? – Reza Sep 06 '19 at 01:23
  • It won't work on a single line, you need to match balanced braces, that's why I asked if the actual string is multiline. – Barmar Sep 06 '19 at 01:29
  • @Barmar so what do you suggest as solution for single line? – Reza Sep 06 '19 at 01:30
  • @Barmar my string is more complicated than this (I simplified for SO question) – Reza Sep 06 '19 at 01:31
  • Show what you tried using `xregexp`. It should be able to do it. – Barmar Sep 06 '19 at 01:31
  • @Barmar it's in the question – Reza Sep 06 '19 at 01:31
  • @Barmar please see this https://repl.it/@RezaRahmati/xregexp – Reza Sep 06 '19 at 01:37

1 Answers1

0

Unfortunately, matchBalanced() is not useful for this, because of this:

An error is thrown if delimiters are unbalanced within the data.

So you can't use it just to find the balanced parts of the string, you can only use it with data that's expected to be balanced -- it returns the outermost substrings. Since what you're looking for are the balanced parts that are nested inside, it won't return them.

Barmar
  • 741,623
  • 53
  • 500
  • 612
  • thanks for answer, it explains why my regexp is not working, but still my problem is not solved – Reza Sep 06 '19 at 01:49
  • See the last line of my answer, it says how you can combine this with other code to solve the problem. – Barmar Sep 06 '19 at 01:50
  • how to find every instance of `messages: ` using regex? – Reza Sep 06 '19 at 01:54
  • Simple: `/messages:/g` – Barmar Sep 06 '19 at 01:55
  • Sorry, I am just confused, that will find `messages: ` then how do I know how far in the string is for that `messages:` and if I found that why do I need to do that match recusrive, would you please add some psudo code about the solution? – Reza Sep 06 '19 at 01:58
  • You can just search the rest of the string for the first balanced object. Then look for the next `messages:` and do it again. – Barmar Sep 06 '19 at 01:59
  • Oh I see, let me try and will get back to you if I couldn't figure it out – Reza Sep 06 '19 at 02:00
  • the solution doesn't work, when I pass rest of string to matchRecursive I get unbalanced token error. see https://repl.it/@RezaRahmati/xregexp – Reza Sep 06 '19 at 13:33
  • Apparently `matchRecursive` doesn't just return the balanced substrings, it requires all the delimiters to be balanced in the entire string. So it's not useful for this. – Barmar Sep 06 '19 at 13:42
  • Is there any other solutions you can think of? – Reza Sep 06 '19 at 13:46
  • Not with JavaScript regular expressions. You need something that implements PCRE so you can use recursion. – Barmar Sep 06 '19 at 13:47