Answers.Body: <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>
  
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2017-03-22T18:01:40.547Z
Answers.Text: Thanks, Brandon. I've tried that but it didn't work. I probably did something wrong.
Answers.UserDisplayName: Jonathan Schofield
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2017-03-22T18:04:44.410Z
Answers.Text: 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.
Answers.UserDisplayName: Jonathan Schofield
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2017-03-22T18:08:14.667Z
Answers.Text: 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 '\'`.
Answers.UserDisplayName: Jonathan Schofield
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2017-03-22T18:08:40.410Z
Answers.Text: @JonathanSchofield `</` probably needs to be `<\\/`
Answers.UserDisplayName: Brandon Kelly
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2017-03-22T18:27:10.200Z
Answers.Text: 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.
Answers.UserDisplayName: Jonathan Schofield
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2017-03-22T17:58:55.787Z
Answers.LastActivityDate: 2017-03-22T17:58:55.787Z
Answers.UserDisplayName: Brandon Kelly
Answers.Body: <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>
  
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2017-03-22T18:13:33.147Z
Answers.LastActivityDate: 2017-03-22T18:48:53.217Z
Answers.LastEditDate: 2017-03-22T18:48:53.217Z
Answers.UserDisplayName: Jonathan Schofield
Body: <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>
  
Comments.ContentLicense: CC BY-SA 3.0
Comments.CreationDate: 2017-03-22T17:41:19.190Z
Comments.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.
Comments.UserDisplayName: Jonathan Schofield
Tags: <replace><regex><markdown>
Title: Using a back reference inside a regex search string within replace filter
ThreadText: # 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[^>]*>(.*?)</\2>)\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[^>]*>(.*?)</\\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?
  
  **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, username_1. 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**: @username_0 `</` 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 username_1’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 %}
  
  ```
  
  
  ---
  
  