Summary of the new feature/enhancement
As a user,
I want to be able to easily use Select-String to find string data in formatted output,
so that I can find and process data in PowerShell more quickly.
By default, when you pass non-string data into the Select-String cmdlet, it will find matches based on the object's ToString() method results. This is great when the ToString output actually represents the data you want to match, but very often ToString results do not represent the data that you see in PowerShell, and this can result in incorrect or failed matches.
For example, consider this script:
# First, capture the date:
$date = Get-Date
# Now, get the current month in string format:
$month = $date.ToString("MMMM")
# Now, look at how the date renders in PowerShell, showing the month as a string
$date
# Now, try to match the month using Select-String. This returns nothing.
Get-Date | Select-String -Pattern $month
That script shows the current date, including the month in string format, but if you try to select that string based on the actual string month, there are no matches. Why does this happen? Because ToString() on DateTime objects returns the date time with a numeric month, not the string month.
Now let's look at a more realistic example:
# Get some services, including the Windows Update service, and filter output on the
# string "Update"
Get-Service wuauserv,bits | Select-String Update
That returns nothing. Why? Because the ToString method on service objects returns the name of service, so you can't filter output based on a partial match of a display name string this way.
Here is one more example:
Get-Process -Id $PID | Format-List * | Select-String Memory
This also returns nothing, because of the ToString method on Format cmdlet output objects returns their type name, none of which match Memory.
It is reasonable for a user to expect to be able to easily and consistently parse/filter output that is rendered in the PowerShell console, but this is not possible unless they pipe to Out-String -Stream before they then pipe that streamed result to Select-String.
Proposed technical implementation details (optional)
[EDIT]: Updated to reflect the parameter name we decided to move forward in the discussion below.
I want to make Select-String better by adding a new -ConsoleOutput switch parameter (or some better parameter name: suggestions welcome) -FromFormattedOutput switch parameter that indicates that you want to select a string based on the console output of the data that is piped into Select-String, which would automatically take care of the formatting and output of non-value and non-string types (and non-MatchInfo, but that's a special case internally for Select-String), and select string matches based on that output rather than based on the ToString method output of individual objects.
Additional details
Personally I would prefer if Select-String worked this way by default for non-value and non-string types, but that would be a breaking change at this point, so that's not an option; however, users who want it to work this way by default can use $PSDefaultParameterValues['Select-String:FromFormattedOutput'] = $true, and that will have the same result.
Summary of the new feature/enhancement
As a user,
I want to be able to easily use
Select-Stringto find string data in formatted output,so that I can find and process data in PowerShell more quickly.
By default, when you pass non-string data into the
Select-Stringcmdlet, it will find matches based on the object'sToString()method results. This is great when theToStringoutput actually represents the data you want to match, but very oftenToStringresults do not represent the data that you see in PowerShell, and this can result in incorrect or failed matches.For example, consider this script:
That script shows the current date, including the month in string format, but if you try to select that string based on the actual string month, there are no matches. Why does this happen? Because
ToString()onDateTimeobjects returns the date time with a numeric month, not the string month.Now let's look at a more realistic example:
That returns nothing. Why? Because the
ToStringmethod on service objects returns the name of service, so you can't filter output based on a partial match of a display name string this way.Here is one more example:
This also returns nothing, because of the
ToStringmethod onFormatcmdlet output objects returns their type name, none of which matchMemory.It is reasonable for a user to expect to be able to easily and consistently parse/filter output that is rendered in the PowerShell console, but this is not possible unless they pipe to
Out-String -Streambefore they then pipe that streamed result toSelect-String.Proposed technical implementation details (optional)
[EDIT]: Updated to reflect the parameter name we decided to move forward in the discussion below.
I want to make
Select-Stringbetter by adding a new-ConsoleOutputswitch parameter (or some better parameter name: suggestions welcome)-FromFormattedOutputswitch parameter that indicates that you want to select a string based on the console output of the data that is piped intoSelect-String, which would automatically take care of the formatting and output of non-value and non-string types (and non-MatchInfo, but that's a special case internally forSelect-String), and select string matches based on that output rather than based on theToStringmethod output of individual objects.Additional details
Personally I would prefer if Select-String worked this way by default for non-value and non-string types, but that would be a breaking change at this point, so that's not an option; however, users who want it to work this way by default can use
$PSDefaultParameterValues['Select-String:FromFormattedOutput'] = $true, and that will have the same result.