2

I have this regex to scan for each loops in my views, it almost does what I want, but not entirely. Im using this regex atm:

(?=({{each\s+([^{}]*)}}((?>(?!{{#?each).|(?1))*){{#each}}))

When I have an each-loop within another each-loop, it shows the matches correctly, but I don't want to inner each loop to be a match. I am planning to process this 2nd match recursively. Here is an example HTML:

<div class="rows-container">
{{each infoItems}}
    <div class="row">
        <div class="row-key"></div>
    </div>

    <div class="sub-container">
    {{each subItems}}
        <div class="row">
            <div class="row-key"></div>
        </div>
    {{#each}}
    </div>
{{#each}}
</div>

<div class="rows-container">
{{each newsItems}}
    <div class="row">
        <div class="row-key"></div>
    </div>
{{#each}}
</div>

Will produce the following results:

//MATCH 1:
1. {{each infoItems}} <div class="row"> <div class="row-key"></div> </div> <div class="sub-container"> {{each subItems}} <div class="row flex-wrap"> <div class="row-key"></div> </div> {{#each}} </div> {{#each}}
2. infoItems
3. <div class="row"> <div class="row-key"></div> </div> <div class="sub-container"> {{each subItems}} <div class="row flex-wrap"> <div class="row-key"></div> </div> {{#each}} </div> 


//MATCH 2:
//This is the match I was trying to exclude:
4. {{each subItems}} <div class="row flex-wrap"> <div class="row-key"></div> </div> {{#each}}
5. subItems
6. <div class="row flex-wrap"> <div class="row-key"></div> </div> 

//MATCH 3:
7. {{each newsItems}} <div class="row"> <div class="row-key"></div> </div> {{#each}}
8. newsItems
9. <div class="row"> <div class="row-key"></div> </div> 

As you can see all I need is: the full result (which is useful for the replace callback), the array name, & the content. I have tried puzzling with the regex,

{{each\s+([^{}]*)}}((?>(?!{{#?each).|(?1))*){{#each}}

This will only give the 2nd & the third, but not the first ='( I'm starting to think I'm in over my head with regexes this complex, losing the understanding of them... but I like to push things.

Is there a way to capture the 1st and 3rd match? with allowing other each loops inside (only 1 inside required.. for now), but not matching them. A little bit of explanation or feedback will be very much appreciated, but I got some time on my hands and I am in for a puzzle.

Maarten Kuijper
  • 304
  • 1
  • 5
  • 17
  • well so far I have met only 1 other situations in my (school) projects. I needed this to create sub lists inside list items, which I had to prepare in class because my code wasn't able to do it (yet). Now I needed it for creating a dropdown with child items below the row. Both situation were rows from the same table with a parent_id... I was thinking of other ways to do it, but every time it results in a loop inside a loop – Maarten Kuijper May 24 '17 at 01:50
  • I could think of a way to prepare the $matches array, and remove the inner each loops, but honnestly I think that is a bit unorthodox. If I can't fix this regex I might have to go with seperate regexes for opening {{each X}} and closing {{#each}} and try to find another way to get the needed strings – Maarten Kuijper May 24 '17 at 01:54
  • 1
    if you remove `(?= ... )` from your pattern, you'll get what you want... https://regex101.com/r/BAgvV8/2 – Sergey Khalitov May 24 '17 at 01:58
  • you just stunned me, loops in loops in loops... something else must have changed? xD still can't believe I haven't had this earlier today. Although I don't get why things get messed up if I remove the outer '( )' to drop that capture., I think I can work with this.. tnx a bunsh! Added an extra capture around {{each\s*(.*?)}} seems to be working fine as well =) – Maarten Kuijper May 24 '17 at 02:16
  • 2
    this case is for recursive pattern https://regex101.com/r/uEydjD/1 as it's more optimized. – Deadooshka May 24 '17 at 02:25
  • amagawt that one looks worse then mandarin language for me xD but its works, tnx! added a capture to it too without too much trouble. How am I supposed to make this question answered? :s still getting used to stacko – Maarten Kuijper May 24 '17 at 02:33
  • 1
    Deadooshka's regex is nice. I would have used [`(?s){{each (\w+)}}(?:(?!{{#?each\b).|(?R))+{{#each}}`](https://regex101.com/r/rn8mv2/1), but the idea to make use of NFA alternative branch order allowing single `{` and `}` inside `{{each}}` is better. Best would be to write (or use an existing) parser for these complex structures. – Wiktor Stribiżew May 24 '17 at 06:22
  • I started using yours again Wiktor :s because I wasnt able to use {{if {editdelete} == yes}} buttons content{{#if}} inside an each . I just need to solve a little processing puzzle which allows me to check for empty – Maarten Kuijper May 24 '17 at 16:38

0 Answers0