Quick tip: replace it (slightly) smarter.

I try to use regular expression as much as I can. Mainly because this gets really “rusty” very quickly when not used. What I like to use very often is PowerShell’s operator –replace. It works wonders, especially when combined with named and numbered captures. But there are situations where this syntax can be hard to apply. I was walking around those issues in the past until I finally came up with solution that seems obvious if you think of it for a minute – so I’m probably not the first one that came up with it. If you did it few years ago – please feel free to look down on me. Puszczam oczko

The problem is that if you want to use named capture in replacement pattern, or mix numbered one with digits there. Whole syntax falls apart, because parser can’t tell where name/ number ends and “free text” starts. This is best understood in examples so here are two that work just fine:

# Works perfect!            
'I want to add some text after this:123' -replace '(:\d+)', '$1text'            
# Capture named, but we use number instead - works!            
'And some text:here' -replace '(?<text>:\w+)','$1Added'            

Sadly, if we want to use name, or add digits immediately after captured text – it won’t work as good:

# Won't work...            
'I want to add some digit after this:123' -replace '(:\d+)', '$1456'            
# Nor this...            
'And some text:here' -replace '(?<text>:\w+)','$text Added'            

You will get literal replacements rather than one that you would expect/ want. The way around it that is (at least from my perspective) most “natural” is to use full variable syntax, rather than simplified one that we are used to. So same as you would need to use it for defining some variable with extremely verbose name:

${My variable has verbose name} = 'Foo'

You can use ${name} syntax, and get away with named/ numbered captures every time you need it:

# Works *every* time!            
'Add digit:123' -replace '(:\d+)', '${1}456'            
'Add text:here' -replace '(?<text>:\w+)', '${text}.Added'

For me – perfect, simple solution. Replace just got (slightly) smarter. Uśmiech


4 thoughts on “Quick tip: replace it (slightly) smarter.

  1. Hi Bartek,
    cool solution, I take note of it! Nonetheless there is something that I don’t get. I know that single quotes don’t do variables replacement so I wonder how is it that this one works: ‘${1}456’ …

    I would have expected this: “${1}456”.

    Never mind, in this context it works, but sometimes I have hard times finding the right syntax because of little obstacles like this one.

    • Yes, that’s not how variables usually work: expand in double-quotes, literal in single. If you would use double-quote here though, PowerShell would try to use PowerShell variables, rather than regex notations. So unless you would have $test, or $1 PowerShell variables defined – it would simply replace it with empty string, not exactly what we try to achieve here.

      • Very nice. I’ll have to remember this.
        Now if they’d let you use a script block delegate (like [regex]::replace() does) that would be really cool!.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s