Regex to match content between string that doesn't include this string

Viewed 57

I need to match a string that start end end with a specific string like [#start, and ,#end]. I use for that the regex /\[#start,(.*?),#end\]/g:

const string = '[#start,foobar,#end]'
const regex = /\[#start,(.*?),#end\]/g

console.log(string.match(regex))

The next step is to add the condition that the match doesn't contains in the middle another match like for example [#start,[#start,foobar,#end],#end]. I use for that a negative look-arounds /\[#start,((?!\[#start,(.*?),#end\]).*?),#end\]/g:

const string = '[#start,[#start,foobar,#end],#end]'
const regex = /\[#start,((?!\[#start,(.*?),#end\]).*?),#end\]/g

console.log(string.match(regex)) // --> will just match "[#start,foobar,#end]"

It's working well so far but the issue is that the start string is little bit more complex because it as to match something like /"#for (.*?) in (.*?)",/g. Example:

const string = '"#for i in [1, 2]",{"id": "[i]"},"#endfor"'
const regex = /"#for (.*?) in (.*?)",(.*?),"#endfor"/g

console.log([...string.matchAll(regex)])

Again I don't want that the 'middle' contains this syntax so I use like the previous example a negative look-arounds "#for (.*?) in (.*?)",(((?!"#for (.*?) in (.*?)",(.*?),"#endfor").)*?),"#endfor":

const string = '"#for i in [1, 2]","#for i in [1, 2]",{"id": "[i]"},"#endfor","#endfor"'
const regex = /"#for (.*?) in (.*?)",(((?!"#for (.*?) in (.*?)",(.*?),"#endfor").)*?),"#endfor"/g

console.log(string.match(regex))

But in this case it still match the first occurance of #for i in [1, 2] instead of just the string in the middle "#for i in [1, 2]",{"id": "[i]"},"#endfor". Any idea what is happening?

For those who wonder why such a regex, I need to use it in the development of the project restapify that enable you to easily mock a rest API with a JSON file structure.

1 Answers

You may use this regex:

#for ((?:(?!#for .*? in .*?",|"#endfor).)*?) in ((?:(?!#for .*? in .*?",|"#endfor).)*?)",((?:(?!#for .*? in .*?",|"#endfor).)*?),"#endfor

RegEx Demo

Code:

const string = '"#for i in [1, 2]","#for i in [1, 2]",{"id": "[i]"},"#endfor","#endfor"';

const regex = /#for ((?:(?!#for .*? in .*?",|"#endfor).)*?) in ((?:(?!#for .*? in .*?",|"#endfor).)*?)",((?:(?!#for .*? in .*?",|"#endfor).)*?),"#endfor/g;

var m = [...string.matchAll(regex)]

if (m)
  console.log(m[0]);

Related