3

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.

0

1 Answer 1

1

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]);

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

5 Comments

Thanks for your help but here it should only match the string "#for i in [1, 2]",{"id": "[i]"},"#endfor" because it doesn't contain another #for ... syntax. In your example the first occurenance of #for i in [1, 2] is matched and that shouldn't be the case.
Thanks a lot for your help. Just a tiny question. With my first regex /"#for (.*?) in (.*?)",(.*?),"#endfor"/g, I'm able with the matchAll method to get all the different components of my string (see my example in the updated question). Sadly with yours I only get the middle part. Do you have any idea what I need to update to have all the 3 different parts? :)
What are the expected matches for const string = '"#for i in [1, 2]","#for i in [1, 2]",{"id": "[i]"},"#endfor","#endfor"';? We can get same with my regex also by using: #for ((?:(?!#for .*? in .*?",|"#endfor).)*?) in ((?:(?!#for .*? in .*?",|"#endfor).)*?)",((?:(?!#for .*? in .*?",|"#endfor).)*?),"#endfor
You can see if you run the third code snippet that you got in the console multiple elements according to the multiple (.*?). With this string the result should be ["\"#for i in [1, 2]\",{\"id\": \"[i]\"},\"#endfor\"", "i", "[1, 2]", "{\"id\": \"[i]\"}"] but with yours regex I got ["#for i in [1, 2]\",{\"id\": \"[i]\"},\"#endfor", "{\"id\": \"[i]\"}". Any idea?
You can see demo with my suggested regex. This shows your expected output.

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.