Flow - character replace pattern with chunk()

Hi, it’s 5am, I can’t sleep, I had these two Flow ideas that are really cool.

First is a super fun trick with

  • chunk()

  • Select

  • join()

  • coalesce()

No loops.
No variables.

First problem - string character replacement - safe HTML normaliser

Let’s start with this string

Test <b>HTML</b> & special chars: < > & " '
Name: O'Brien

Now imagine this text is:

  • coming from Dataverse

  • pasted by a user

  • generated by AI

  • injected into HTML email

  • rendered inside a PDF

If you don’t escape it properly… things break.

We want to safely replace:

Character Replace With
< &lt;
> &gt;
" &quot;
' (optional smart quote)

Power Automate doesn’t give us a multi-replace expression. You’ve probably done this type of replace-replace before

replace(
      replace(
        replace(
          replace(
            replace(
              string(outputs('Compose')),
              '&','&amp;'
            ),
            '<','&lt;'
          ),
          '>','&gt;'
        ),
        '"','&quot;'
      ),
      '''','&#39;'
    )

So the clever hack I have is this:

1. Use chunk to break string into char array

chunk(outputs('Compose'),1)

2. Use Select action to map this array with a formula that replaces certain characters

Select
from: 
  chunk(outputs('Compose'),1)
select: 
  coalesce(
    if(equals(item(),'&'),'&amp;',null),
    if(equals(item(),'<'),'&lt;',null),
    if(equals(item(),'>'),'&gt;',null),
    if(equals(item(),'"'),'&quot;',null),
    if(equals(item(),''''),'’',null),
    item(),
    null
  )

We are testing each character in order:

  1. If < → return &lt;

  2. If > → return &gt;

  3. If " → return &quot;

  4. If ' → return

  5. Otherwise → return original character

coalesce() returns the first non-null value.

3. join it back together

join(body('Select'),'')

Why not just use Replace?

You could chain:

replace(replace(replace(...)))

But:
  • It becomes unreadable fast

  • Order matters (you can double-encode)

  • It doesn’t scale well

  • It’s painful to debug

Using chunk() + Select():

  • You see exactly what happens per character

  • It’s safe

  • It’s predictable

  • It’s extensible

It’s basically a mini parsing engine.

The Hidden Insight

The real trick isn’t escaping characters.
The trick is this:

Turn string → array → transform → join.

Once you realise Select is a map function…