Introduction
In last Monday’s blog post, Fun With PowerShell Strings, I covered a lot of the basics around PowerShell Strings. One thing we didn’t get into though was some of the special formatting commands you can use with PowerShell.
Specifically, this can control the output when we embed a numeric value inside a string. Passing in special formatting instructions will make it easy to display values with commas, as currency, or even as hexidecimal.
For all of the examples, we’ll display the code, then under it the result of our code. In this article I’ll be using PowerShell Core, 7.1.3, and VSCode. The examples should work in PowerShell 5.1 in the PowerShell IDE, although they’ve not been tested there.
To run a snippet of code highlight the lines you want to execute, then in VSCode press F8 or in the IDE F5. You can display the contents of an array variable (or any variable) by highlighting it and using F8/F5.
How it Works
PowerShell supports the C# / C / C++ style of string formatting. Let’s take a look at this example.
[string]::Format("There are {0} items.", $items)
Inside our string we have {0}
. This is a placeholder, when a C style language sees this it will look for the first variable after the string and put that into placeholder 0
.
PowerShell of course always wants to make life easier on us, so we can use this much simpler format.
"There are {0} items." -f $items
In PowerShell we have our string, including the placeholder. After it we have a -f to let PowerShell know the following items will be copied into the placeholders. In this case, the value in $items
will be inserted into the {0}
placeholder.
It’s not necessary to use a variable, we could have just hardcoded a value.
"There are {0} items." -f 33
What if we had multiple items? Well we’d just use multiple placeholders (all on one line).
"There are {0} items in the location {1}." -f $items, $loc
In this example, $items
will go into the {0}
and the value in $loc
will get inserted into placeholder {1}
.
You can even repeat a placeholder.
"There's {0} items in {1}. {0} is a lot of items!" -f $items, $loc
Now, if you’ve read my previous post you’re probably thinking “wait, wouldn’t string interpolation make all these unnecessary?”
And in these examples you are correct, with string interpolation you could have used the much easier to read syntax.
"There are $items items."
So why use the placeholder style? Well it turns out the placeholder syntax includes some extra syntax which will allow you to format values passed in. Let’s take a look at some examples.
Number
In the placeholder, after the placeholder position ( 0
in these examples ) you can put a colon :
, then a letter that indicates the formatting style. Then another number which indicates the decimal places to retain.
"N0 {0:N0} formatted" -f 12345678.119
Result:
N0 12,345,678 formatted
In this example, after the colon we have the letter N
. This lets PowerShell know we want this to be formatted as a numeric value, and to include commas to separate the numbers.
In this example after the letter N
we have another number, a 0
. This indicates how many decimal places to retain in the output.
Here’s another example where we’ll include two decimal places.
"N2 {0:N2} formatted" -f 12345678.119
Result:
N2 12,345,678.12 formatted
As you can see, it follows the normal rules for rounding up the output. The next to the last last number, 1
, was rounded up to 2
since the number after it was a 9
.
Often we want to display numbers as right aligned, so the last digit will line up in our output. This means we want to display a number of spaces in front of it. PowerShell includes a feature for this too.
"N0 {0,8:N0} formatted" -f 123.119
Result:
N0 123 formatted
After the place holder we have a comma then a number ( here 0,8
). This tells PowerShell we want the value for this placeholder to be eight characters in width.
In the output, PowerShell saw the final value, 123
, was three characters wide. So it subtracted three from eight and put five spaces in front of the 123
so the entire output became eight characters in width.
A common question is “what if the output is longer than the width passed in?”. For example, you used 0,3
but your input to the placeholder was a value of 123456
? In that case PowerShell will still format it as 123,456
but will not add any spaces before the number. This could result in some misaligned output in your display, but at least the accurate value will still be shown.
Currency
Using the C
format instruction, PowerShell can display the results in currency format. It will use the default currency symbol for your computer’s language / location. Since I’m in the United States it will use a dollar sign.
"C0 {0:C0} formatted" -f 12345678.1234
"C2 {0:C2} formatted" -f 12345678.1234
"C2 {0,20:C2} formatted" -f 12345678.1234
Result:
C0 $12,345,678 formatted
C2 $12,345,678.12 formatted
C2 $12,345,678.12 formatted
Currency acts very similar to the Number format, the only real difference is the addition of your location’s currency symbol in the formatted output.
Percentage
PowerShell also has the ability to display values in a percentage format.
"P0 {0:P0} formatted" -f 0.1234
"P2 {0:P2} formatted" -f 0.1234
"P2 {0,8:P2} formatted" -f 0.1234
Result:
P0 12% formatted
P2 12.34% formatted
P2 12.34% formatted
Make sure to notice that PowerShell will take the decimal amount and automatically convert the percentage for you. Thus, if you want to display 12%
, you have to pass in 0.12
.
Hex
Next up on the list is Hexadecimal notation. PowerShell supports two methods for doing Hex values. In the first, it will take a standard number (base 10) and convert it to hexadecimal then display it.
"X0 0x{0:X0} formatted" -f 1234
Result:
X0 0x4D2 formatted
In this case we passed in the number 1234. PowerShell converted it to hex then displayed it.
What if the value were already in hex format though, and we just wanted to display it? In PowerShell, we indicate a number is in hex by placing a 0x
in front of it. So we just pass in our number with 0x in front to the string.
"X0 0x{0:X0} formatted" -f 0x4D2
Result:
X0 0x4D2 formatted
When PowerShell saw the 0x
on the front of 0x4D2
, it knew this value was already in hex format and didn’t try to convert it, it simply displayed our value.
Decimal
The name of the next formatter we’ll look at is Decimal. It’s a bit misnamed though, because it’s really just for formatting integer based numbers. As a matter of fact, if you try use with a non integer value, such as 33.42, it will error out.
Let’s look at the most basic form of Decimal.
"D0 {0:D0} formatted" -f 123
Result:
D0 123 formatted
Pretty simple, it just displays the value. So you can guess D is the formatter for decimal, but what is D0
? The number after the D indicates how many spaces we want to zero pad to.
In other words, we want the string to be a certain number of characters long, so the number indicates that length. It will then put zeros to the left to pad it out. Let’s look at this example to make it clear.
"D8 {0:D8} formatted" -f 123
Result:
D8 00000123 formatted
In this case, the D8
indicated we wanted eight characters in decimal formatting. PowerShell converted 123
to a string that was three characters long, so it put five zero’s in front to make the total length eight.
You can also add the placeholder comma value formatting to make a value a certain width wide. In these two examples, the first will act like a Number format. The second though will let you use leading zeros, but still set the total space.
"D0 {0,9:D0} formatted" -f 123
"D0 {0,9:D6} formatted" -f 123
Result:
D0 123 formatted
D0 0000123 formatted
In the first example, it made the output nine characters wide by placing six spaces in front of the 123
. In the second example, it first made the 123
six characters by placing 000
on front, resulting in 000123
.
It then took the resulting 000123
and made that nine wide by placing three spaces in front. As you can see, PowerShell is very flexible when formatting this way.
A reminder, as stated earlier Decimal is only for integers. If I were to try using -f 123.1
as an input it would error out.
Custom Date Formatting
In addition to the other formats, PowerShell provides the ability to create custom date outputs. You do so using these characters, note they are case sensitive.
M / MM | One or Two character month number |
d / dd | One or two character day of the month number. |
yy / yyyy | Two or four digit year number. |
h / hh | One or two digit hour of the day in 12 hour format |
H / HH | One or two digit hour of the day in 24 hour format |
m / mm | One or two digit minute of the hour |
s / ss | One or two digit second of the minute |
Let’s see these used in a series of examples.
"Today is {0:M/d/yy}." -f $(Get-Date)
"Today is {0,10:MM/dd/yyyy}." -f $(Get-Date)
"Today is {0,10:dd/MM/yyyy}." -f $(Get-Date)
"Today is {0,10:yyyyMMdd}." -f $(Get-Date)
"Today is {0,10:MM/dd/yyyy hh:mm:ss}." -f $(Get-Date)
"Today is {0,10:MM/dd/yyyy HH:mm:ss}." -f $(Get-Date)
Result:
Today is 7/18/21.
Today is 07/18/2021.
Today is 18/07/2021.
Today is 20210718.
Today is 07/18/2021 04:59:56.
Today is 07/18/2021 16:59:56.
In all of these, I passed in the current date (as I’m writing this) using Get-Date, but any date based variable would have worked.
In the output I’ve arranged the date parts in a variety of common manners. You can use these or create your own custom formats. For example you may wish to use a dash instead of a slash to separate the date parts.
Custom Number Formatting
Let’s say you lived in London, where the pound was your default currency. But you are part of a multinational company and need to produce output to send to your coworkers in the United States. You don’t want to have to change your computer to a US language just to get the $ symbol.
You can fix this by using custom formatting. In these examples, when it sees a character such as the $ it will just keep it in the output. When it sees #,
(a pound sign followed by a comma) it will know to use commas in the output.
When it sees just a #
sign it will put a number there if it has one, otherwise a space, and when it sees 0
it will put a number from the passed in data, or a zero if there is no number there. These examples will clarify it.
Note each one is on it’s own line, WordPress is wrapping the -f part to the next line for space reasons. Additionally, in this and other examples I’ve chosen to add spaces to line up the demos for readability, this isn’t a requirement and you can format however you need.
"Custom 0, 25 $ #,##0.0000 = {0,25:$ #,##0.0000} " -f 123456789.012000005
"Custom 0, 25 $ #,##0.0000 = {0,25:$ #,##0.00} " -f 123456789.012000005
"Custom 0, 25 $ ##0.0000 = {0,25:$ ##0.00} " -f 123456789.012000005
Result:
Custom 0, 25 $ #,##0.0000 = $ 123,456,789.0120
Custom 0, 25 $ #,##0.0000 = $ 123,456,789.01
Custom 0, 25 $ ##0.0000 = $ 123456789.01
Using Formatting with Variables
It’s possible to create a formatted value, then assign that to a variable. Let’s take a look at this slightly more complex example.
$vTday = "{0,8:N0}" -f 134567
$vYest = "{0,8:N0}" -f 23546
$tday = "{0:MM/dd/yyyy}" -f $(Get-Date)
$yest = "{0:MM/dd/yyyy}" -f $((Get-Date).AddDays(-1))
$output = "Visitors to ArcaneCode.com`r`n"
$output += "$tday had $vTday visitors`r`n"
$output += "$yest had $vYest visitors"
$output
Result:
Visitors to ArcaneCode.com
07/18/2021 had 134,567 visitors
07/17/2021 had 23,546 visitors
The first two lines you’ve seen a few times by now. I’m simply taking a number, formatting it with commas and making it eight spaces wide.
The next line you’ve seen as well, I take the current date, format to MM/dd/yyyy
format and assign to $tday
.
The $yest
line is slightly more complex, but only because I’m doing some date math. The (Get-Date)
will get the current date, but create a date object from it. Essentially I have a date variable type but without a variable name.
Because I have a date datatype I can employ a method of the date datatype, AddDays
. This will let me add a number of days to the date, or if you pass in a negative value subtract days. Thus AddDays(-1)
will give me yesterday’s date. I then have to wrap it all in $()
so PowerShell will evaluate the entire expression before passing it back to the placeholder.
Finally I’m using the += operand to concatenate several strings together for a nice output. Note the formatted dates, and how the visitors number right aligns nicely.
Conclusion
While string interpolation makes creating output strings easy, knowing how to use placeholders can make creating formatted output even easier, allowing you to create output with numeric values that align neatly, or creating custom date formatting.
The demos in this course came from my Pluralsight course PowerShell 7 Quick Start for Developers on Linux, macOS and Windows, one of many PowerShell courses I have on Pluralsight. All of my courses are linked on my About Me page.
If you don’t have a Pluralsight subscription, just go to https://pluralsight.com. At the top is a Try For Free button you can use to get a free 10 day subscription to Pluralsight, with which you can watch my courses, or any other course on the site. Once there just search for my name, Robert Cain, to see all the courses I have.