Search code examples
powershellexpressionselect-string

Use Select-String to get the single word matching pattern from files


I am trying to get only the word when using Select-String, but instead it is returning the whole string

Select-String -Path .\*.ps1 -Pattern '-Az' -Exclude "Get-AzAccessToken","-Azure","Get-AzContext"

I want to get all words in all .ps1 files that contain '-Az', for example 'New-AzHierarchy'


Solution

    • Select-String outputs objects of type Microsoft.PowerShell.Commands.MatchInfo by default, which supplement the whole line (input object) on which a match was found (.Line property) with metadata about the match (in PowerShell (Core) 7+, you can use -Raw to directly output the matching lines (input objects) only).

      • Note that in the default display output, it appears that only the matching lines are printed, with PowerShell (Core) 7+ now highlighting the part that matched the pattern(s).
    • Select-String's -Include / -Exclude parameters do not modify what patterns are matched; instead, they modify the -Path argument to further narrow down the set of input files. Since a wildcard expression as part of the -Path argument is usually sufficient, these parameters are rarely used.


    Therefore:

    • Use the objects in the .Matches collection property Select-String's output objects to access the part of the line that actually matched the given pattern(s).

      • Since you want to capture entire command names that contain substring -Az, such as New-AzHierarchy, you must use a regex pattern that also captures the relevant surrounding characters: \w+-Az\w+
    • The simplest way to exclude specific matches is to filter them out afterwards, using a Where-Object call.

    # Note: -AllMatches ensures that if there are *multiple* matches 
    #        on a single line, they are all reported.
    Select-String -Path .\*.ps1 -Pattern '\w+-Az\w+' -AllMatches |
      ForEach-Object { $_.Matches.Value } |
      Where-Object { $_ -notin 'Get-AzAccessToken', '-Azure', 'Get-AzContext' }