Select-String -Context

Select-String -Context

  • Comments 4

A lot of people use Select-String but I haven’t seen much discussion of the –Context parameter.   This is an awesome feature that we added in V2.  If you haven’t tried it, you should spend a few minutes experimenting.  I can guarantee you that will you be glad you did.

Let’s see what the HELP has to say about the Context parameter:

 

PS> Get-Help Select-String -Parameter Context

-Context <Int32[]>
    Captures the specified number of lines before and after the line with the m
    atch. This allows you to view the match in context.

    If you enter one number as the value of this parameter, that number determi
    nes the number of lines captured before and after the match. If you enter t
    wo numbers as the value, the first number determines the number of lines be
    fore the match and the second number determines the number of lines after t
    he match.

    In the default display, lines with a match are indicated by a right angle b
    racket (ASCII 62) in the first column of the display. Unmarked lines are th
    e context.

    This parameter does not change the number of objects generated by Select-St
    ring. Select-String generates one MatchInfo (Microsoft.PowerShell.Commands.
    MatchInfo) object for each match. The context is stored as an array of stri
    ngs in the Context property of the object.

    When you pipe the output of a Select-String command to another Select-Strin
    g command, the receiving command searches only the text in the matched line
     (the value of the Line property of the MatchInfo object), not the text in
    the context lines. As a result, the Context parameter is not valid on the r
    eceiving Select-String command.

    When the context includes a match, the MatchInfo object for each match incl
    udes all of the context lines, but the overlapping lines appear only once i
    n the display.

    Required?                    false
    Position?                    named
    Default value
    Accept pipeline input?       false
    Accept wildcard characters?  false

 

Let’s have some fun.  I’m going to use Superstar James O’Neil’s Hypervisor Management Library to experiment with.  He has a number of functions the work with NICs.  Let’s party.

PS> #First Let's find the functions
PS> dir *.ps1 |Select-String function.*NIC

network.ps1:3:Function Add-VMNIC
network.ps1:64:Function Get-VMNic
network.ps1:94:Function Get-VMNicport
network.ps1:104:Function Get-VMnicSwitch
network.ps1:121:Function Get-VMNICVLAN
network.ps1:282:Function Remove-VMNIC
network.ps1:332:Function remove-VMSwitchNIC
network.ps1:366:Function Select-VMNIC
network.ps1:392:Function Set-VMNICAddress
network.ps1:422:Function Set-VMNICSwitch
network.ps1:459:Function Set-VMNICVLAN

PS> # That gave me too many so let's add a $ to the end of the SEARCH STRING
PS> # That indicates a Line end
PS> dir *.ps1 |Select-String function.*NIC$

network.ps1:3:Function Add-VMNIC
network.ps1:64:Function Get-VMNic
network.ps1:282:Function Remove-VMNIC
network.ps1:366:Function Select-VMNIC

PS> # Let's see 1 line before and after each matching line
PS> dir *.ps1 |Select-String function.*NIC$ -Context 1

  network.ps1:2:
> network.ps1:3:Function Add-VMNIC
  network.ps1:4:{# .ExternalHelp  MAML-VMNetwork.XML
  network.ps1:63:
> network.ps1:64:Function Get-VMNic
  network.ps1:65:{# .ExternalHelp  MAML-VMNetwork.XML
  network.ps1:281:
> network.ps1:282:Function Remove-VMNIC
  network.ps1:283:{# .ExternalHelp  MAML-VMNetwork.XML
  network.ps1:365:
> network.ps1:366:Function Select-VMNIC
  network.ps1:367:{# .ExternalHelp  MAML-VMNetwork.XML

PS> # Notice the line numbers and that the matching line has a > in front


PS> # Now let's try 3 lines before and after the matching line
PS> dir *.ps1 |Select-String function.*NIC$ -Context 3

  network.ps1:1:
  network.ps1:2:
> network.ps1:3:Function Add-VMNIC
  network.ps1:4:{# .ExternalHelp  MAML-VMNetwork.XML
  network.ps1:5:    [CmdletBinding(SupportsShouldProcess=$true)]
  network.ps1:6:    param(
  network.ps1:61:}
  network.ps1:62:
  network.ps1:63:
> network.ps1:64:Function Get-VMNic
  network.ps1:65:{# .ExternalHelp  MAML-VMNetwork.XML
  network.ps1:66:    param(
  network.ps1:67:        [parameter(ValueFromPipeline = $true)]
  network.ps1:279:}
  network.ps1:280:
  network.ps1:281:
> network.ps1:282:Function Remove-VMNIC
  network.ps1:283:{# .ExternalHelp  MAML-VMNetwork.XML
  network.ps1:284:    [CmdletBinding(SupportsShouldProcess=$true)]
  network.ps1:285:    param(
  network.ps1:363:
  network.ps1:364:
  network.ps1:365:
> network.ps1:366:Function Select-VMNIC
  network.ps1:367:{# .ExternalHelp  MAML-VMNetwork.XML
  network.ps1:368:    param(
  network.ps1:369:        [parameter(ValueFromPipeline = $true)]

PS> # The line before is boring so let's get rid of that and then see a
PS> # few lines after
PS> dir *.ps1 |Select-String function.*NIC$ -Context 0,3

> network.ps1:3:Function Add-VMNIC
  network.ps1:4:{# .ExternalHelp  MAML-VMNetwork.XML
  network.ps1:5:    [CmdletBinding(SupportsShouldProcess=$true)]
  network.ps1:6:    param(
> network.ps1:64:Function Get-VMNic
  network.ps1:65:{# .ExternalHelp  MAML-VMNetwork.XML
  network.ps1:66:    param(
  network.ps1:67:        [parameter(ValueFromPipeline = $true)]
> network.ps1:282:Function Remove-VMNIC
  network.ps1:283:{# .ExternalHelp  MAML-VMNetwork.XML
  network.ps1:284:    [CmdletBinding(SupportsShouldProcess=$true)]
  network.ps1:285:    param(
> network.ps1:366:Function Select-VMNIC
  network.ps1:367:{# .ExternalHelp  MAML-VMNetwork.XML
  network.ps1:368:    param(
  network.ps1:369:        [parameter(ValueFromPipeline = $true)]

 

 

PS> # Let's take a look at the body of Remove-VMNIC
PS> dir *.ps1 |Select-String function.*Remove-VMNIC$ -Context 0,20

> network.ps1:282:Function Remove-VMNIC
  network.ps1:283:{# .ExternalHelp  MAML-VMNetwork.XML
  network.ps1:284:    [CmdletBinding(SupportsShouldProcess=$true)]
  network.ps1:285:    param(
  network.ps1:286:        [parameter(Mandatory = $true ,  ValueFromPipeline = $true)]
  network.ps1:287:        $Nic,
  network.ps1:288:
  network.ps1:289:        $PSC,
  network.ps1:290:        [switch]$force,
  network.ps1:291:
  network.ps1:292:        $VM, $Server #VM no longer required, but preserved for compatibility with V1
  network.ps1:293:    )
  network.ps1:294:    process {
  network.ps1:295:        if ($psc -eq $null)  {$psc = $pscmdlet} ; if (-not $PSBoundParameters.psc) {$PSBoundParameter
s.add("psc",$psc)}
  network.ps1:296:        if ($NIC -is [Array] ) {[Void]$PSBoundParameters.Remove("NIC") ;  $NIC | ForEach-object {Remo
ve-VMNIC  -NIC $_  @PSBoundParameters}}
  network.ps1:297:        if ($nic -is [System.Management.ManagementObject])  {remove-VMRasd -rasd $NIC -PSC $psc }
  network.ps1:298:            # note: In V1 the switch port was removed before removing the NIC, but this is done autom
atically.
  network.ps1:299:    }
  network.ps1:300:}
  network.ps1:301:
  network.ps1:302:

 

Party on your own.  You are going to love –Context!

Experiment!  Enjoy!  Engage!

Jeffrey Snover [MSFT]
Distinguished Engineer
Visit the Windows PowerShell Team blog at:    http://blogs.msdn.com/PowerShell
Visit the Windows PowerShell ScriptCenter at:  http://www.microsoft.com/technet/scriptcenter/hubs/msh.mspx

Leave a Comment
  • Please add 4 and 8 and type the answer here:
  • Post
  • Holy crap, I remember that from the DCL SEARCH command! I think it was $SEARCH /WINDOW=(1,1) I used to use it all the time to hunt for a string in log files and the n lines before and after.

    The more I play with Powershell, the more I'm taken back to my youth as a VMS system manager. :) Thanks Jeffrey!

    mike

  • @Mike

    EXACTLY!!!

    Jeffrey Snover [MSFT]

    Distinguished Engineer

    Visit the Windows PowerShell Team blog at:    http://blogs.msdn.com/PowerShell

    Visit the Windows PowerShell ScriptCenter at:  http://www.microsoft.com/technet/scriptcenter/hubs/msh.mspx

  • Context ist fine, but is there any way I can pipe it? So I can work with all the lines in the output and not only the lines in the match?

  • Wow. DCL. It has been sooo long! :-)

    Is there a way to specify I want everthing after a match to the end of a file? I basically want to find a special line in the file, and then grab all the text after that. I've been using -context 0,10000, but perhaps there is a better way.

Page 1 of 1 (4 items)