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

CC BY-SA 4.0
2018-09-19T14:29:40.690Z
2018-09-19T14:29:40.690Z
Robin Schambach
<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>

CC BY-SA 4.0
2018-09-19T14:36:25.853Z
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?
Emma Swann
CC BY-SA 4.0
2018-09-19T18:56:59.373Z
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.
Sam Hernandez
CC BY-SA 4.0
2018-09-19T14:26:01.910Z
2018-09-19T19:00:58.553Z
2018-09-19T19:00:58.553Z
Sam Hernandez
<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>

<replace>
Replace in the first instance?
# 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('
    ', '') | 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
{{ 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 %}
  Duis mollis, est non commodo luctus.
  Nulla vitae elit libero, a pharetra augue.
  Donec sed odio dui. Maecenas faucibus mollis interdum. 
{% endset %}

{% set inserted %}
  Inserted text
{% endset %}

{# Split text into array on closing  tags #}
{% for paragraph in content | split('') %}
  {# Add the closing tag back, except for possible empty lines  #}
  {% set paragraph = paragraph | trim | length ? paragraph ~ '' : '' %}
  {# 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('') %}
    {% set paragraph = paragraph | trim | length ? paragraph ~ '' : '' %}
    {{ paragraph | raw }}
    {% if loop.index == 1 %}
      {{ insertContent }}
    {% endif %}
  {% endfor %}
{% endmacro %}

{% from _self import insertAfterFirstParagraph %}

{% set addThisHtml %}
  Add this paragraph
{% 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 %}

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.
Aside: Craft overrides the default Twig replace filter to use PHP's 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+?/', '', 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.  

---

