0

Another hard regex in javascript:

I have this string:

    <td style="padding:0 2%">{% for product in products.pos01 %}    
<table class="box-item" item-editable="" style="float:left;padding-bottom:10px; width:32%;border-spacing: 0px; border: 0px; border-collapse: collapse;"><tr><td style=" padding:10px 5px; vertical-align:top ">
<a href="**|product.url|**" class="button view-deal" style="padding:8px 10px; background-color: #fc5d26; text-decoration:none; display:inline-block; text-align:center; color:#fff; font-size:12px;margin:0px; line-height:140%;text-transform:uppercase">view deal</a></div></td></tr></table>{% if (loop.index0-2) is divisibleby 3 %}</td></tr><tr>
<td style="padding:0 2%">{% endif %}{% endfor %}
 </td>

I'm trying to get content inside any loops from the string {% for ... %} and {% endfor %}

I've tried with, but can't get

/({% for (!?%})+ %})((!?endfor)*){% endfor %}/gm

but didn't work

1
  • Perhaps, this one: \{%\s*for[\s\S]*?%}([\s\S]*?)\{%\s*endfor\s*%}? Commented Aug 21, 2015 at 16:34

3 Answers 3

2

I think you suppose to use a pattern similar to this

Regex

(?<={% for[^%]*%})((?:.|\n)*)(?={% endfor %})

Explanation

(?<={% for[^%]*%}) : use lookbehind to searching for pattern {% for[^%]*%}

(?={% endfor %}) : use lookahead to searching for text {% endfor %}

((?:.|\n)*) : a message between a for loop which is captured by variable $1

But in case if your language do not support lookaround, you just use this

Regex

({% for[^%]*%})((?:.|\n)*)({% endfor %})

Explanation

({% for[^%]*%}) : capture pattern {% for[^%]*%} to variable $1

({% endfor %}) : capture pattern {% endfor %} to variable $3

((?:.|\n)*) : a message between a for loop which is captured by $2

Just modify my regex according to a restriction in your language then you will done this.

Edit

As I search, I think Javascript do not support lookaround and another thing {, } need to be escape by \. I already tested regex using some online regex tester for Javascript and I get this.

(\{% for[^%]*%\})((?:.|\n)*)(\{% endfor %\})

to get a text that you want, you just use variable $2.

Additional

In case you want to capture message inside nested loop e.g.

Example Message

{% for product in products.pos01 %} 
    ...
    {% for product in products.pos02 %}
         "messages"
    {% endfor %}
    ...
{% endfor %}

To capture "messages" inside this nested loop you just need to modify my previous regex to

(\{% for[^%]*%\}(?:.|\n)*\{% for[^%]*%\})((?:.|\n)*)(\{% endfor %\}(?:.|\n)*\{% endfor %\})

Explanation

(\{% for[^%]*%\}(?:.|\n)*\{% for[^%]*%\}) : means "start of for loop" following by "any characters including newline" and following by "start of for loop"

((?:.|\n)*): our target message

(\{% endfor %\}(?:.|\n)*\{% endfor %\}) : means "end of for loop" following by "any characters including newline" and following by "end of for loop"

Notice that I just rearrange my previous regex to done this little bit more complicated job.

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

4 Comments

@AlexandruRada. It means: any character . or | a new line \n as many as possible (?:)* - without grouping
what if there are multiple {% for %} loops? That's why I tried to exclude with (!?endfor) but didn't work...
You mean you want to capture them start from the most outer for loop right?
As I test, I think my regex is still working. Unless you want to specify that which level of your nested loop, that is more complicated.
1

Try this regex:

{% for [^\0]+?{% endfor %}

Regex live here.

Explanation:

{% for            # search for text `{% for `
[^\0]+?           # while not input's end
{% endfor %}      # search for the next `{% endfor %}`

Or, if you want groups:

{% (for [^\0]+?)%}([^\0]+?){% endfor %}

Regex live here.

Hope it helps.

Comments

0

If you're trying to get what is within {% for ... %} and {% endfor %} this might work:

/%}([\W\w]*){%/gm

Explanation:

%} matches the characters %} literally
\W match any non-word character [^a-zA-Z0-9_]
\w match any word character [a-zA-Z0-9_]
{% matches the characters {% literally
g modifier: global. All matches (don't return on first match)
m modifier: multi-line.

Example:

https://regex101.com/r/pM3oX7/1

It's unclear if you are wanting to get the text within the %} {% or also include that part.

2 Comments

And what if you add this text {% if ... to the end of atual input?
@WashingtonGuedes: What if... yes I love that one... here, I'll give you one to use on yours I {% forgot... what if... ewlrkjkendfor %}...and not endfor %}? ... neat! :D

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.