Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

powershell select-string not working correctly

I'm a beginner to powershell and having I suspect what will be a simple problem. I'm trying to do the following command, but it returns nothing as a result and I don't understand why.

I'm trying to get the description of the current section of bcdedit. If I do:

bcdedit /enum | select-string "identifier.*current" -context 0,3  

It returns the following:

> identifier {current}  
device partition=C:  
path \WINDOWS\system32\winload.exe  
description Windows 8.1  

So why doesn't the following return description Windows 8.1?

bcdedit /enum | select-string "identifier.*current" -context 0,3 | select-string "description"  

Instead it returns nothing at all.

Any information on this would be appreciated.

like image 317
user2443973 Avatar asked Feb 21 '14 20:02

user2443973


People also ask

How do I select a part of a string in PowerShell?

To find a string inside of a string with PowerShell, you can use the Substring() method. This method is found on every string object in PowerShell. The first argument to pass to the Substring() method is the position of the leftmost character. In this case, the leftmost character is T .

What does $_ mean in PowerShell?

The “$_” is said to be the pipeline variable in PowerShell. The “$_” variable is an alias to PowerShell's automatic variable named “$PSItem“. It has multiple use cases such as filtering an item or referring to any specific object.

Is Select-string case sensitive?

Select-String uses the Pattern parameter to specify HELLO. The CaseSensitive parameter specifies that the case must match only the upper-case pattern. SimpleMatch is an optional parameter and specifies that the string in the pattern isn't interpreted as a regular expression.

How do I search for a string in PowerShell?

You can use it like Grep in UNIX and Findstr in Windows with Select-String in PowerShell. Select-String is based on lines of text. By default, Select-String finds the first match in each line and, for each match, it displays the file name, line number, and all text in the line containing the match.


2 Answers

You don't get the result you expect, because Select-String doesn't output strings, but MatchInfo objects. If you pipe the output of your first Select-String into the Get-Member or Format-List cmdlet, you'll get something like this:

PS C:\> bcdedit /enum | Select-String "identifier.*current" -Context 0,3 | Get-Member

   TypeName: Microsoft.PowerShell.Commands.MatchInfo

Name         MemberType Definition
----         ---------- ----------
Equals       Method     bool Equals(System.Object obj)
GetHashCode  Method     int GetHashCode()
GetType      Method     type GetType()
RelativePath Method     string RelativePath(string directory)
ToString     Method     string ToString(), string ToString(string directory)
Context      Property   Microsoft.PowerShell.Commands.MatchInfoContext Context {get;set;}
Filename     Property   string Filename {get;}
IgnoreCase   Property   bool IgnoreCase {get;set;}
Line         Property   string Line {get;set;}
LineNumber   Property   int LineNumber {get;set;}
Matches      Property   System.Text.RegularExpressions.Match[] Matches {get;set;}
Path         Property   string Path {get;set;}
Pattern      Property   string Pattern {get;set;}

PS C:\> bcdedit /enum | Select-String "identifier.*current" -Context 0,3 | Format-List *

IgnoreCase : True
LineNumber : 17
Line       : identifier              {current}
Filename   : InputStream
Path       : InputStream
Pattern    : identifier.*current
Context    : Microsoft.PowerShell.Commands.MatchInfoContext
Matches    : {identifier              {current}

The Line property contains the actual matching line, and the Context property contains child properties with the pre- and post-context. Since the description line you're looking for is in the PostContext child property, you need something like this for extracting that line:

bcdedit /enum | Select-String "identifier.*current" -Context 0,3 |
  Select-Object -Expand Context |
  Select-Object -Expand PostContext |
  Select-String 'description'

Bottom line: Select-String does work correctly. It just doesn't work the way you expect.

like image 179
Ansgar Wiechers Avatar answered Oct 22 '22 09:10

Ansgar Wiechers


Select-String returns MatchInfo objects, not just the string data displayed. That data is taken from the Line and Context properties of the MatchInfo object.

Try this:

 bcdedit /enum | select-string "identifier.*current" -context 0,3 | format-list

And you'll see the various properties of the MatchInfo object.

Note that the Context property is displayed as Microsoft.PowerShell.Commands.MatchInfoContext You'll need to drill down into this object further to get more information:

(bcdedit /enum | select-string "identifier.*current" -context 0,3).context | format-list

There you'll see that the context property is another object with PreContext and PostContext properties, where the actual Pre and PostContext lines are.

So:

(bcdedit /enum | select-string "identifier.*current" -context 0,3).Context.PostContext | Select-String 'description'

Will get the description line from the postcontext matches.

Or you can do this:

[string](bcdedit /enum | select-string "identifier.*current" -context 0,3) -split "`n" -match 'description'
like image 21
mjolinor Avatar answered Oct 22 '22 08:10

mjolinor