<p>Backreferences within the regex are normally defined as <code>\1</code>, <code>\2</code>, etc. In the <code>|replace</code> filter you need to escape all backslashes, so it’ll be <code>\\1</code>, <code>\\2</code>, etc.</p>

CC BY-SA 3.0
2017-03-22T18:01:40.547Z
Thanks, Brandon. I've tried that but it didn't work. I probably did something wrong.
Jonathan Schofield
CC BY-SA 3.0
2017-03-22T18:04:44.410Z
I've realised that if I don't mind adding an attribute to _all_ parsedown generated tags, as opposed to child tags only (no nested tags), then I don't need to worry about the closing tag at all, and therefore the back reference within the pattern. Which means I have something that works.
Jonathan Schofield
CC BY-SA 3.0
2017-03-22T18:08:14.667Z
If I use the following (as per your suggestion I think)… `elems|replace('/(<([a-z][a-z0-9]*)\\b[^>]*>(.*?)</\\2>)\s+/', '\\1>,')`, then I get `preg_replace(): Unknown modifier '\'`.
Jonathan Schofield
CC BY-SA 3.0
2017-03-22T18:08:40.410Z
@JonathanSchofield `</` probably needs to be `<\\/`
Brandon Kelly
CC BY-SA 3.0
2017-03-22T18:27:10.200Z
Thanks. At least `<\\/\\2>` stops an error being thrown. But the HTML tag search fails. Thanks for your help. I may persist, or I might just go with my workaround.
Jonathan Schofield
CC BY-SA 3.0
2017-03-22T17:58:55.787Z
2017-03-22T17:58:55.787Z
Brandon Kelly
<p>A workaround in light of my comments on Brandon’s reply…</p>

<p>If I ignore the attempt to act on child tags only, I can search for opening tags of all generated elements (regardless of whether they are nested) with…</p>

<p><code>{% set elems = elems|replace('/(&lt;[a-z][a-z0-9]*\\b[^&gt;]*&gt;)/', '$1&gt;,') %}</code></p>

<p>and then…</p>

<pre><code>{# Convert elems to an array #}
    {% set elems = elems|split('&gt;,') %}

{% for el in elems %}
    {# Add an id attribute to each opening tag -- eg: id="el123-1" #}
    {{ el|replace('/(&lt;[a-z][a-z0-9]*)/', '$1 id="el' ~ blockId ~ '-' ~ loop.index ~ '"')|raw }}
{% endfor %}
</code></pre>

CC BY-SA 3.0
2017-03-22T18:13:33.147Z
2017-03-22T18:48:53.217Z
2017-03-22T18:48:53.217Z
Jonathan Schofield
<p>I’m trying to insert a programmatically generated <code>id</code> attribute into child elements of parsedown processed text. I'm aware that Craft’s twig replace filter incorporates <a href="http://php.net/manual/en/function.preg-replace.php" rel="nofollow noreferrer">preg_replace</a>, so…</p>

<p>I have a regex search string that finds an HTML tag and its contents. It includes an inner back reference to make sure that the closing tag matches the opening tag (as opposed to some nested closing tag)…</p>

<p><code>(&lt;([a-z][a-z0-9]*)\b[^&gt;]*&gt;(.*?)&lt;/\2&gt;)\s+</code></p>

<p>I can use <code>$1</code> inside <code>|replace</code> to refer to the entire tag found by the outer parentheses…</p>

<p><code>elems|replace('/(&lt;([a-z][a-z0-9]*)\\b[^&gt;]*&gt;(.*?)&lt;/\\2&gt;)\s/', '$1&gt;,')</code></p>

<p>…and then work with the results, but the problem (I think) is the syntax for the back reference inside the search string itself.</p>

<p>I've tried the following without success…</p>

<p><code>elems|replace('/(&lt;([a-z][a-z0-9]*)\\b[^&gt;]*&gt;(.*?)&lt;/$2&gt;)\s/', '$1&gt;,')</code>
<code>elems|replace('/(&lt;([a-z][a-z0-9]*)\\b[^&gt;]*&gt;(.*?)&lt;/\\$2&gt;)\s/', '$1&gt;,')</code></p>

<p>Where am I going wrong? Is this even possible with <strong>preg_replace</strong>? Or is there a better way to go about injecting attributes into parsedown processed text?</p>

CC BY-SA 3.0
2017-03-22T17:41:19.190Z
The idea of the above is to prepare the ground for converting the parsedown output (elems) into an array, and then loop through the array to insert an id attribute, and then join the array to achieve the final output.
Jonathan Schofield
<replace><regex><markdown>
Using a back reference inside a regex search string within replace filter
# Using a back reference inside a regex search string within replace filter

(Asked by: username_0 on 2017-03-22)

I’m trying to insert a programmatically generated `id` attribute into child elements of parsedown processed text. I'm aware that Craft’s twig replace filter incorporates [preg\_replace](http://php.net/manual/en/function.preg-replace.php), so…

I have a regex search string that finds an HTML tag and its contents. It includes an inner back reference to make sure that the closing tag matches the opening tag (as opposed to some nested closing tag)…

`(<([a-z][a-z0-9]*)\b[^>]*>(.*?))\s+`

I can use `$1` inside `|replace` to refer to the entire tag found by the outer parentheses…

`elems|replace('/(<([a-z][a-z0-9]*)\\b[^>]*>(.*?))\s/', '$1>,')`

…and then work with the results, but the problem (I think) is the syntax for the back reference inside the search string itself.

I've tried the following without success…

`elems|replace('/(<([a-z][a-z0-9]*)\\b[^>]*>(.*?))\s/', '$1>,')`
`elems|replace('/(<([a-z][a-z0-9]*)\\b[^>]*>(.*?))\s/', '$1>,')`

Where am I going wrong? Is this even possible with **preg\_replace**? Or is there a better way to go about injecting attributes into parsedown processed text?

**Tags:** replace, regex, markdown
> **Comments:**
> **username_0**: The idea of the above is to prepare the ground for converting the parsedown output (elems) into an array, and then loop through the array to insert an id attribute, and then join the array to achieve the final output.  

---

## 2 answers

### Answer by username_1 on 2017-03-22. Score: 1

Backreferences within the regex are normally defined as `\1`, `\2`, etc. In the `|replace` filter you need to escape all backslashes, so it’ll be `\\1`, `\\2`, etc.

> **Comments:**
> **username_0**: Thanks, Brandon. I've tried that but it didn't work. I probably did something wrong.  
> **username_0**: I've realised that if I don't mind adding an attribute to _all_ parsedown generated tags, as opposed to child tags only (no nested tags), then I don't need to worry about the closing tag at all, and therefore the back reference within the pattern. Which means I have something that works.  
> **username_0**: If I use the following (as per your suggestion I think)… `elems|replace('/(<([a-z][a-z0-9]*)\\b[^>]*>(.*?)</\\2>)\s+/', '\\1>,')`, then I get `preg_replace(): Unknown modifier '\'`.  
> **username_1**: @JonathanSchofield `</` probably needs to be `<\\/`  
> **username_0**: Thanks. At least `<\\/\\2>` stops an error being thrown. But the HTML tag search fails. Thanks for your help. I may persist, or I might just go with my workaround.  

---

### Answer by username_0 on 2017-03-22. Score: 1

A workaround in light of my comments on Brandon’s reply…
If I ignore the attempt to act on child tags only, I can search for opening tags of all generated elements (regardless of whether they are nested) with…
{% set elems = elems|replace('/(<[a-z][a-z0-9]*\\b[^>]*>)/', '$1>,') %}
and then…
{# Convert elems to an array #}
    {% set elems = elems|split('>,') %}

{% for el in elems %}
    {# Add an id attribute to each opening tag -- eg: id="el123-1" #}
    {{ el|replace('/(<[a-z][a-z0-9]*)/', '$1 id="el' ~ blockId ~ '-' ~ loop.index ~ '"')|raw }}
{% endfor %}


---

