I have an array and use select-string to find duplicates.
$2 = $arraySNOW | Select-String -Pattern $request
The process usually finds 2 items and but each item is now rapped inside @{}
object and I can not access the value for a specific property
$2[0]
@{number=63887630; request=abc560vi}
$2 | Get-Member
TypeName: Microsoft.PowerShell.Commands.MatchInfo
$2.gettype()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True Object[] System.Array
How to pull the value of the request for both items in $2
?
Santiago Squarzon has provided the crucial pointer:
Select-String
is for string searches, whereas you want OO techniques to filter your objects, so you should use Where-Object
to filter your objects by a property value of interest:
# Filters the input objects by whether their .Request property
# matches the specified regex pattern.
$arraySNOW | Where-Object Request -match $request
The above passes the matching input objects through, so you can access their properties as needed; e.g., to get the .number
property values of the matching objects:
$arraySNOW | Where-Object request -match $request |
ForEach-Object number # alternatively: Select-Object -ExpandProperty number
Or, more succinctly, using member-access enumeration:
($arraySNOW | Where-Object request -match $request).number
As for what you tried:
$arraySNOW | Select-String -Pattern $request
returns any number of Microsoft.PowerShell.Commands.MatchInfo
instances describing the string matches performed on the input objects.
.Line
property contains the text of the input line or stringified input object (see below) that was matched; in PowerShell (Core) 7+, you can obtain this text directly with the -Raw
switch.If Select-Object
emits two ore more objects and you capture them in a variables ($2 = ...
) PowerShell automatically collects them in an [object[]]
(System.Object[]
) array for you.
Piping an array (a list-like enumerable) to Get-Member
invariably results in the array's enumeration, so that Get-Member
reports the distinct types among its elements - hence the report of type Microsoft.PowerShell.Commands.MatchInfo
By contrast, calling .GetType()
on any object - whether it is a scalar or an array / list / collection - reports its own type.
The for-display representation of a MatchInfo
instance you saw with $2[0]
is in essence the value of its .Line
property:
Non-string input to Select-Object
is implicitly stringified, and the stringified value is both used for matching and reported via the .Line
property.
Therefore, you lose the object identity of the input, and simply get a string representation of it.
The specific form of the string representation you saw - @{number=63887630; request=abc560vi}
resembles PowerShell hashtable literals - but is, in fact, how [pscustomobject]
instances are stringified - see this answer for details.
With many other types, the implicit stringification results in useless representations, namely simply the full type name of the input object, given that .ToString()
stringification (with some custom functionality overlaid) is applied (e.g., stringifying a hashtable results in string 'System.Collections.Hashtable'
; try @{ foo = 1 }.ToString()
)
Given that PowerShell has a rich for-display output-formatting system that provides much more helpful representations of most types, it is unfortunate that Select-String
doesn't apply PowerShell's formatting implicitly; see GitHub issue #10726 for a discussion.