Search code examples
powershellscriptingpowershell-cmdlet

How to display output in a custom format using Format-Custom, in PowerShell scripting?


Get-CIMInstance -ClassName Win32_Printer | Select-Object Name, @{label="IPAddress";expression={($_.comment | Select-string -Pattern "\d{1,3}(\.\d{1,3}){3}" -AllMatches).Matches.value}}

The above command gives me the following output:

Name                          IPAddress      
----                          ---------      
Webex Document Loader         100.100.100.100
OneNote (Desktop)             111.111.111.111
Microsoft XPS Document Writer 120.120.120.120
Microsoft Print to PDF        123.123.123.123
Fax                           127.127.127.127

I'm looking for some cmdlet that can be piped into the above command so that I can customize the output into the following:

Webex Document Loader(100.100.100.100), OneNote (Desktop)(111.111.111.111), Microsoft XPS Document Writer(120.120.120.120), Microsoft Print to PDF(123.123.123.123), Fax(127.127.127.127)

Thanks in advance


Solution

  • Since PowerShell Core 7.0 this can be done using Join-String:

    Get-CIMInstance -ClassName Win32_Printer | 
        Select-Object Name, @{label="IPAddress";expression={($_.comment | Select-string -Pattern "\d{1,3}(\.\d{1,3}){3}" -AllMatches).Matches.value}} |
        Join-String -Property { '{0}({1})' -f $_.Name, $_.IPAddress } -Separator ', '
    

    The Join-String cmdlet is used to both format and join the input objects into a single string. Parameter -Separator should be self-explanatory. The argument for -Property specifies a calculated property that defines a script block which formats the input object. The format operator -f is used to cleanly produce the desired format. Alternatively it could be done using string interpolation only, e. g. "$($_.Name)($($_.IPAddress))" but I don't like all the parenthesis.


    Alternative solution for PowerShell versions older than 7.0, that don't provide Join-String:

    (Get-CIMInstance -ClassName Win32_Printer | 
        Select-Object Name, @{label="IPAddress";expression={($_.comment | Select-string -Pattern "\d{1,3}(\.\d{1,3}){3}" -AllMatches).Matches.value}} |
        ForEach-Object {'{0}({1})' -f $_.Name, $_.IPAddress}) -join ', '
    

    Here the -join operator is used to produce a single one-line string. The grouping operator is used to turn the pipeline into an expression that collects all output into an array that the -join operator can take as its left-hand-side argument.