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, 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)…


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

  • 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. Commented Mar 22, 2017 at 17:41

2 Answers 2


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.

  • Thanks, Brandon. I've tried that but it didn't work. I probably did something wrong. Commented Mar 22, 2017 at 18:01
  • 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. Commented Mar 22, 2017 at 18:04
  • 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 '\'. Commented Mar 22, 2017 at 18:08
  • @JonathanSchofield </ probably needs to be <\\/ Commented Mar 22, 2017 at 18:08
  • 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. Commented Mar 22, 2017 at 18:27

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 %}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.