PowerShell’s format operator


I just came across a tip at the Hey, Scripting Guy! Blog about grouping numbers and controlling the decimal places after the dot, that describes the use of the ToString method of the number (int) object. Since I prefer using PowerShell’s -f format operator for that, and it’s description in the PowerShell help topics (Get-Help about_Operators) is not too detailed, I found myself writing this post.

To use the format operator, you need a string with placeholders, the –f format operator, and an array of values to place into the placeholders. e.g. ‘This is my {0} usage of the {1} operator’ –f ‘first’, ‘-f’

You guessed right. It would output: This is my first usage of the -f operator

The placeholder syntax is: {<index>[,<alignment>][:<formatString>]}

The index is the zero-based index of the argument whose string representation is to be included at this position in the string. If this argument is null, an empty string will be included at this position in the string. it can be repeated several times in the string. for example:

'Pow{0}rSh{0}ll {1}' -f 'e', 'rocks!'

The alignment is a signed integer that indicates the total length of the field into which the argument is inserted and whether it is right-aligned (a positive integer) or left-aligned (a negative integer). If you omit alignment, the string representation of the corresponding argument is inserted in a field with no leading or trailing spaces.

'ServerName: {0,16}. Uptime: {1} days(s)' -f $ComputerName, $UptimeInDays

The formatString is a string that specifies the format of the corresponding argument's result string. If you omit the formatString, the corresponding argument's parameterless ToString method is called to produce its string representation. for example:

'ServerName: {0,16}. Uptime: {1:N2} hour(s)' -f $ComputerName, $UptimeInHours

or an even more useful example would be:

'C:\Temp\myScriptsLogFile_{0:yyyyMMddHHmmss}.log' -f (Get-Date)

 

So, instead of using the ToString as explained in the tip:

(1000*1000).tostring("N3")

you would use the format operator like this:

'{0:N3}' -f (1000*1000)

 

More examples for the format operator:

To display percentages: '{0:p}' -f (1/4)

To display numbers that represent currency: '{0:c}' -f (100)

To display numbers in hexadecimal: '0x{0:x8}' -f (12)

To create a list of server names with a padding prefix when it’s less then 10 (e.g. SERVER05)

1..10 | % { 'SERVER{0:d2}' -f $_ }

 

More information on formatting numbers can be found at: http://msdn.microsoft.com/en-us/library/dwhawy9k(v=vs.71).aspx 

and on formatting dates at: http://msdn.microsoft.com/en-us/library/system.globalization.datetimeformatinfo(v=vs.71).aspx

 

HTH,

\Martin.

Comments (3)

  1. CodeMaster Bob says:

    Format operator gotcha:

    -f has higher precendence than */+- (https://technet.microsoft.com/en-us/library/hh847842.aspx). Therefore

    "{0:X}" -f 3*3

    parses as

    ("{0:X}" -f 3) * 3

    giving the string "333".

    Found this out the hard way when trying to find the maximum allowed size for "format.exe" of a FAT32 volume (in hex):

    "{0:X}" -f 32kb*4197717

  2. CodeMaster Bob says:

    Another possible gotcha:

    The list of arguments to -f is an array. It can be a literal (as in 1,2,3), a variable containing an array or a pipeline which produces an array. Any of those may also produce a single item because there is a constructor for [object[]] that will take a single
    object or a scalar:

    ([object[]]5).gettype()

    IsPublic IsSerial Name BaseType
    ——– ——– —- ——–
    True True Object[] System.Array

    ([object[]]5).length
    1

    The Gotcha is that the argument must be an array of OBJECT.

    Thus

    "{0} is {1} of {2}" -f "The argument","an array","[String]"

    works fine. But

    [Uint32[]]$uints = 5,6
    "uints[0] = {0:X} and uints[1] = {1:X}" -f $uints
    Error formatting a string: Index (zero based) must be greater than or equal to zero and less than the size of the argument list..
    At line:1 char:1
    + "uints[0] = {0:X} and uints[1] = {1:X}" -f $uints
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : InvalidOperation: (uints[0] = {0:X} and uints[1]
    = {1:X}:String) [], RuntimeException
    + FullyQualifiedErrorId : FormatError

    This is because [Uint32[]] is an array of Uint32 but is a single object so there is no second argument for {1:X}.

    Solution, construct an object array from the scalar array:

    "uints[0] = {0:X} and uints[1] = {1:X}" -f [object[]]$uints

Skip to main content