Answers.Body: <p>Another way would be to create a Twig filter that does what is explained here <a href="https://stackoverflow.com/a/1252710/5604055">replace only first appearance of string</a></p>
  
  <pre><code>{{ str|replace_once() }} 
  </code></pre>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2018-09-19T14:29:40.690Z
Answers.LastActivityDate: 2018-09-19T14:29:40.690Z
Answers.UserDisplayName: Robin Schambach
Answers.Body: <p>I can't think of a way to do this with Twig's <code>replace</code> filter but it is possible to do it by splitting the text into an array and iterating over it like so:</p>
  
  <pre><code>{% set content %}
    &lt;p&gt;Duis mollis, est non commodo luctus.&lt;/p&gt;
    &lt;p&gt;Nulla vitae elit libero, a pharetra augue.&lt;/p&gt;
    &lt;p&gt;Donec sed odio dui. Maecenas faucibus mollis interdum. &lt;/p&gt;
  {% endset %}
  
  {% set inserted %}
    &lt;p&gt;Inserted text&lt;/p&gt;
  {% endset %}
  
  {# Split text into array on closing &lt;/p&gt; tags #}
  {% for paragraph in content | split('&lt;/p&gt;') %}
    {# Add the closing tag back, except for possible empty lines  #}
    {% set paragraph = paragraph | trim | length ? paragraph ~ '&lt;/p&gt;' : '' %}
    {# Render the text as raw html #}
    {{ paragraph | raw }}
    {# Render the inserted paragraph on the first loop #}
    {% if loop.index == 1 %}
      {{ inserted }}
    {% endif %}
  {% endfor %}
  </code></pre>
  
  <p>Edit: Per your question in the comment about the context, this is a good use case for a macro. This code is untested, but you might try something like this.</p>
  
  <pre><code>{% macro insertAfterFirstParagraph(content, insertContent) %}
    {% for paragraph in content | split('&lt;/p&gt;') %}
      {% set paragraph = paragraph | trim | length ? paragraph ~ '&lt;/p&gt;' : '' %}
      {{ paragraph | raw }}
      {% if loop.index == 1 %}
        {{ insertContent }}
      {% endif %}
    {% endfor %}
  {% endmacro %}
  
  {% from _self import insertAfterFirstParagraph %}
  
  {% set addThisHtml %}
    &lt;p&gt;Add this paragraph&lt;/p&gt;
  {% endset %}
  
  {% set isAdded = false %}
  {% for block in entry.myMatrixField %}
    {% if block.type == 'body' and loop.index &gt; 5 and isAdded == false %}
      {{ insertAfterFirstParagraph(block.bodyField, addThisHtml) }}
      {% set isAdded = true %}
    {% else %}
      {{ block.bodyField }}
    {% endif %}
  {% endfor %}
  </code></pre>
  
  <p>Robin's suggestion to build a custom Twig filter in a plugin (or module) would be the cleanest solution, but the Twig code above should get the job done.</p>
  
  <p>Aside: <a href="https://github.com/craftcms/cms/blob/develop/src/web/twig/Extension.php#L431" rel="nofollow noreferrer">Craft overrides the default Twig replace filter</a> to use PHP's <a href="http://php.net/preg_replace" rel="nofollow noreferrer">preg_replace()</a> function but that filter doesn't accept the last two optional arguments, <code>limit</code> and <code>count</code>. If it did, then something like this could have worked:</p>
  
  <pre><code>replace('/&lt;\\/p&gt;\\s+?&lt;p&gt;/', '&lt;/p&gt;&lt;div id="test"&gt;&lt;/div&gt;&lt;p&gt;', 1)
  </code></pre>
  
  <p>Maybe a feature request is in order.</p>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2018-09-19T14:36:25.853Z
Answers.Text: This is excellent in that it has reduced the replacement to once per block, but I obviously should've included more of the code! 
  
          {% if block.type == "body" %}
                {% if loop.index > 5 %} 
  
  Is before the code above - so it's running now for every body block after a certain point. Are there any ways to find the first body block after a certain number of blocks?
Answers.UserDisplayName: Emma Swann
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2018-09-19T18:56:59.373Z
Answers.Text: I updated the answer, but I have a hunch you need to count how many 'body' blocks the loop encountered. That can be done with a variable you increment every time it hits one.
Answers.UserDisplayName: Sam Hernandez
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2018-09-19T14:26:01.910Z
Answers.LastActivityDate: 2018-09-19T19:00:58.553Z
Answers.LastEditDate: 2018-09-19T19:00:58.553Z
Answers.UserDisplayName: Sam Hernandez
Body: <p>I am trying to insert a div that'll call an ad between two paragraphs of copy text.</p>
  
  <p>However, I'd like to do it only one instance. The current replace code I'm using is this - which is inserting my test code multiple times. </p>
  
  <pre><code>    {% set str = block.bodyText %}
      {{ str | replace('&lt;/p&gt;
      &lt;p&gt;', '&lt;/p&gt;&lt;div id="test"&gt;&lt;/div&gt;&lt;p&gt;') | smartypants }}
  </code></pre>
  
  <p>Is it possible?</p>
  
Tags: <replace>
Title: Replace in the first instance?
ThreadText: # Replace in the first instance?
  
  (Asked by: username_0 on 2018-09-19)
  
  I am trying to insert a div that'll call an ad between two paragraphs of copy text.
  
  However, I'd like to do it only one instance. The current replace code I'm using is this - which is inserting my test code multiple times.
  
  ```
      {% set str = block.bodyText %}
      {{ str | replace('</p>
      <p>', '</p><div id="test"></div><p>') | smartypants }}
  
  ```
  
  Is it possible?
  
  **Tags:** replace
  
  
  ---
  
  ## 2 answers
  
  ### Answer by username_1 on 2018-09-19. Score: 1
  
  Another way would be to create a Twig filter that does what is explained here [replace only first appearance of string](https://stackoverflow.com/a/1252710/5604055)
  
  ```
  {{ str|replace_once() }} 
  
  ```
  
  
  ---
  
  ### Answer by username_2 on 2018-09-19. Score: 1
  
  I can't think of a way to do this with Twig's `replace` filter but it is possible to do it by splitting the text into an array and iterating over it like so:
  
  ```
  {% set content %}
    <p>Duis mollis, est non commodo luctus.</p>
    <p>Nulla vitae elit libero, a pharetra augue.</p>
    <p>Donec sed odio dui. Maecenas faucibus mollis interdum. </p>
  {% endset %}
  
  {% set inserted %}
    <p>Inserted text</p>
  {% endset %}
  
  {# Split text into array on closing </p> tags #}
  {% for paragraph in content | split('</p>') %}
    {# Add the closing tag back, except for possible empty lines  #}
    {% set paragraph = paragraph | trim | length ? paragraph ~ '</p>' : '' %}
    {# Render the text as raw html #}
    {{ paragraph | raw }}
    {# Render the inserted paragraph on the first loop #}
    {% if loop.index == 1 %}
      {{ inserted }}
    {% endif %}
  {% endfor %}
  
  ```
  
  Edit: Per your question in the comment about the context, this is a good use case for a macro. This code is untested, but you might try something like this.
  
  ```
  {% macro insertAfterFirstParagraph(content, insertContent) %}
    {% for paragraph in content | split('</p>') %}
      {% set paragraph = paragraph | trim | length ? paragraph ~ '</p>' : '' %}
      {{ paragraph | raw }}
      {% if loop.index == 1 %}
        {{ insertContent }}
      {% endif %}
    {% endfor %}
  {% endmacro %}
  
  {% from _self import insertAfterFirstParagraph %}
  
  {% set addThisHtml %}
    <p>Add this paragraph</p>
  {% endset %}
  
  {% set isAdded = false %}
  {% for block in entry.myMatrixField %}
    {% if block.type == 'body' and loop.index > 5 and isAdded == false %}
      {{ insertAfterFirstParagraph(block.bodyField, addThisHtml) }}
      {% set isAdded = true %}
    {% else %}
      {{ block.bodyField }}
    {% endif %}
  {% endfor %}
  
  ```
  
  username_1's suggestion to build a custom Twig filter in a plugin (or module) would be the cleanest solution, but the Twig code above should get the job done.
  
  Aside: [Craft overrides the default Twig replace filter](https://github.com/craftcms/cms/blob/develop/src/web/twig/Extension.php#L431) to use PHP's [preg\_replace()](http://php.net/preg_replace) function but that filter doesn't accept the last two optional arguments, `limit` and `count`. If it did, then something like this could have worked:
  
  ```
  replace('/<\\/p>\\s+?<p>/', '</p><div id="test"></div><p>', 1)
  
  ```
  
  Maybe a feature request is in order.
  
  > **Comments:**
  > **username_0**: This is excellent in that it has reduced the replacement to once per block, but I obviously should've included more of the code!           {% if block.type == "body" %}               {% if loop.index > 5 %}   Is before the code above - so it's running now for every body block after a certain point. Are there any ways to find the first body block after a certain number of blocks?  
  > **username_2**: I updated the answer, but I have a hunch you need to count how many 'body' blocks the loop encountered. That can be done with a variable you increment every time it hits one.  
  
  ---
  
  