Training
Get a free hour of SANS training

Experience SANS training through course previews.

Learn More
Learning Paths
Can't find what you are looking for?

Let us help.

Contact us
Resources
Join the SANS Community

Become a member for instant access to our free resources.

Sign Up
For Organizations
Interested in developing a training plan to fit your organization’s needs?

We're here to help.

Contact Us
Talk with an expert

Month of PowerShell: String Substitution

In this article we'll look at some rules for working with string substitution, and some examples to leverage in your own PowerShell scripts.

Authored byJoshua Wright
Joshua Wright

#monthofpowershell

When working with variables in PowerShell, you can leverage built-in support for PowerShell variable string substitution. In this article we'll look at some rules for working with string substitution, and some examples to leverage in your own PowerShell scripts.

Some Rules for String Substitution

String substitution is something you will use in scripts and other short PowerShell 1-liners where you have a variable that you want to expand in a message. For example:

PS C:\Users\Sec504> $name = Read-Host "Tell me your name"
Tell me your name: Josh
PS C:\Users\Sec504> Write-Host "Nice to meet you, $name"
Nice to meet you, Josh

Instead of using string concatenation to merge static strings and variables together, you can embed the variable inside of the quoted string. There are a few rules though:

PS C:\Users\Sec504> $name = Read-Host "Tell me your name"
Tell me your name: Mick
PS C:\Users\Sec504> Write-Host 'Nice to meet you, $name'
Nice to meet you, $name

Rule 1: Variables are expanded in strings with double quotes.

If you specify a string with single quotes, it will treat the variable [code]$name[/code] a literal value, and not a variable to substitute. Also:

PS C:\Users\Sec504> Write-Host "Do you love PowerShell, $name?"
Do you love PowerShell,
PS C:\Users\Sec504> Write-Host "Do you love PowerShell, $name, or whoever you are?"
Do you love PowerShell, Mick, or whoever you are?

Rule 2: Add curly braces to be explicit around variable names

Some characters around variables are treated as part of the variable name, and not punctuation in the string, but this isn't always intuitive. The Microsoft documentation on PowerShell variables says:

In the case of [code]"Do you love PowerShell, $name?"[/code], PowerShell interprets the variable name as [code]$name?[/code], which doesn't exist and returns an empty string. In cases like this, you can surround the variable name in curly braces to force PowerShell to interpret the variable name in the way you want:

PS C:\Users\Sec504> Write-Host "Do you love PowerShell, ${name}?"
Do you love PowerShell, Mick?

Rule 3: Be careful with the backtick

PowerShell also offers support for escape sequences, starting with a backtick [code] [/code][code] followed by a letter. This is most often seen as [/code][code] [/code]n `` to add a newline:

PS C:\Users\Sec504> $age = Read-Host "Please enter your age.`nBe honest please"
Please enter your age.
Be honest please: 47
PS C:\Users\Sec504> Write-Host "The user is $age."
The user is 47.

The backtick can also be used to escape a literal character in a string. Let's say you needed to have a literal [code]"[/code] in your string -- you can escape the [code]"[/code] with a preceding backtick:

PS C:\Users\Sec504> $pass = Read-Host -AsSecureString "Enter your password (do not include `" in the string)"
Enter your password (do not include " in the string): **********

Examples

Let's apply these concepts into some practical examples.

User Messages

Let's say you want to allow a user to specify a directory name, and you report on the number of files in the directory. Here's a short script, [code]countfiles.ps1[/code]:

$dirName = Read-Host "Enter the directory name"
$count = (Get-ChildItem -Path $dirName | Measure-Object).Count
Write-Host "There are $count files in the directory $dirName"

Invoking the script the user specifies the directory, and they get the answer. No string concatenation needed!

PS C:\Users\Sec504> .\countfiles.ps1
Enter the directory name: C:\Windows
There are 101 files in the directory C:\Windows
PS C:\Users\Sec504> .\countfiles.ps1
Enter the directory name: C:\Tools
There are 46 files in the directory C:\Tools

Escape Sequences

Let's say you have a script that is about to do something that is irrevocable, like deleting thousands of users from Active Directory. You might want to give the script user a heads-up, and a chance to terminate the script before the damage is done.

Write-Host "Press CTRL+C before the timer expires to stop the script."
For ($i = 9 ; $i -ne 0; $i--) {
    Write-Host -NoNewline "$i`b" ;
    Start-Sleep 1
}
Write-Host "Deleting users now..."
# Not actually deleting any users

These lines use a [code]ForEach-Object[/code] loop (shortened to [code]For[/code], here), decrementing the variable [code]$i[/code] from 9 to 0. The [code]Write-Host[/code] line suppresses the automatic newline with [code]NoNewline[/code] and moves the cursor back to the beginning of the line after displaying the current value of [code]$i[/code]. This gives us a dramatic countdown allowing the user to press CTRL+C to stop the script.

Summary

In this article we looked at a topic all PowerShell users should understand: string substitution. PowerShell allows us to expand the value stored in a variable within a string, often eliminating the need to perform string concatenation. There are a few rules though: the string must be specified in double quotes, it is sometimes necessary to surround the variable name with curly braces, and the backtick character has special meaning. Keep these rules in mind, and you'll be leverage this powerful feature in all of your future PowerShell work!

Until next time!

-Joshua Wright


Joshua Wright is the author of SANS SEC504: Hacker Tools, Techniques, and Incident Handling, a faculty fellow for the SANS Institute, and a senior technical director at Counter Hack.

Month of PowerShell: String Substitution | SANS Institute