simple PowerShell Select-String Pattern - powershell

Why doesn't the PowerShell script
Get-NetRoute | Select-String -Pattern "255"
Get-NetRoute | Select-String -Pattern 255
Get-NetRoute | Select-String -Pattern '255'
Get-NetRoute | Select-String -Pattern '.*255.*'
give any result? Whats wrong with the Pattern?

The Select-String cmdlet is designed to work on string objects. The output of a Get-NetRoute cmdlet is an array.
For your code to work, you would have to convert it to a string object like this.
(Get-NetRoute | out-string).split("`n") | Select-String -Pattern "255"
But I doubt it would be very helpful if you intend to use the results down the lane.
What you really need is Where-object.
Get-NetRoute | Where-Object {$_.DestinationPrefix -like "*255*"}. Hope that helps.

Select-String will interpret Get-NetRoute as a single string (the output is a single object), so you need to split it up using the -Stream switch. Note that ipconfig | select-string would not have the same problem as it is a DOS command and so by default PowerShell will split it per line, but for PowerShell commands you need to do this when you want to do line by line interrogation since the pipeline is passing a single object, so you are doing it right to use Select-String, but just have to understand how it interprets input from the pipeline and then it'll work fine:
Get-NetRoute | Out-String -Stream | Select-String -Pattern "255"

Related

How do I find substring after using select-string in powershell?

How do I continue to get the 12345 as output?
file.txt
MyText: 12345
myscript
Get-Content file.txt | Select-String "MyText:" | Select-Object Line
Now I would like to save last five characters, how to I retreive them?
The Select-String cmdlet -Pattern parameter expects a regex - so you can get your desired output by capturing the five digits. Note that the Select-String cmdlet also takes a -Path parameter to retrieve the content of a file. This means you can omit the first Get-Content command:
(Select-String -Path .\file.txt -Pattern 'MyText: (\d{5})').Matches.Groups[1].Value

grep gci output in powershell

I am trying to determine if some environment variables are set (for postgres environment). They usually start with PG. (E.g. PGUSER, PGPASSWORD, etc). The following command does output it. (Provided I set it previously).
gci env:* | sort name | more
To eliminate the scrolling I tried the following:
gci env:* | sort name | select-string "PG"
This doesn't return anything. What am I doing wrong here?
Edit: the alternative I have for now:
gci env:* | sort name | % { $var = $_.Name + ":" + $_.Value; Write-Output $var } | select-string "PG"
There must be a better alternative.
You're using the wrong mindset. Don't try to work with PowerShell like everything is a string. That's Unix-like thinking, and it's going to work as well as driving nails with a screwdiver. You need to switch to object-oriented thinking because in PowerShell you're working with objects 99% of the time.
Generally, you would just do this for something as simple as what you're looking for:
Get-ChildItem Env:PG* | Sort-Object -Property Name
If the globbing that Get-ChildItem supports doesn't work, you would want to use Where-Object with the -like operator which is similar globbing to what Get-ChildItem can do:
Get-ChildItem Env:* | Where-Object Name -like 'PG*' | Sort-Object -Property Name
If you need to search values, you can do it like this:
Get-ChildItem Env:* | Where-Object Value -like 'PG*' | Sort-Object -Property Name
And if you want to do both, you'd use the full synax of Where-Object:
Get-ChildItem Env:* | Where-Object { $_.Name -like 'PG*' -or $_.Value -like 'PG*' } | Sort-Object -Property Name
Or you can use the -match operator, which lets you specify a .Net regular expression:
Get-ChildItem Env:* | Where-Object Name -match '^PG' | Sort-Object -Property Name
Or if you know exactly what you're looking for:
$Vars = 'PGUSER', 'PGPASSWORD'
Get-ChildItem Env:* | Where-Object Name -in $Vars | Sort-Object -Property Name
Remembering, of course, that PowerShell is usually case-insensitive. You can specify -clike, -cmatch, -cin, etc. if you want case-sensitive operators.
Alternately, you can use the $env: automatic variable namespace.
if ($null -eq $env:PGUSER) { 'Not set' }
See also Get-Help about_Environment_Variables.
Beware that setting environment variables permanently is not exactly self-evident. It's described briefly in the above link, but the bottom line is that you have to call [System.Environment]::SetEnvironmentVariable(), which you can find documented here. In Windows land, environment variables are basically legacy features with the exception of Windows OS level variables (like PATH) so they're no longer supported like you might expect.
Your approach to how this command should work and your instinct that there has to be a better alternative is exactly correct. This is quite a frustrating issue in my mind and I also asked a variation on this question a few days back.
Select-String only handles strings and what you are passing to it in the above is not a string, so it returns nothing. Obviously, you might think that since Select-String requires a string, that it would implicitly change it into a string, but no. So the next thing to consider is to change it to a string, but that creates even more confusion.
gci env:* | sort name | out-string | select-string "Pro"
So now you just get everything returned. What's happening here is that out-string returns all lines as a single string, so if there is any hit for "Pro" you get everything returned.
What you need to do is to use out-string -stream which splits the string up by linebreaks so that you get a string per line, and only then do you get rational output.
gci env:* | sort name | out-string -stream | select-string "Pro"
More on this here: Using PowerShell sls (Select-String) vs grep vs findstr. The github request linked to in there is trying to change the functionality so that select-string will implicitly have an out-string -stream in the background so that your original command will work.
Often we need strings to output results and there is nothing wrong with wanting to manipulate strings (in fact, it depends what you need of course - if you need to do further object manipulations, keep it as an object for that, but if you just need the string output, you should not have to jump through hoops to get that!). If you use a string-manipulation tool like select-string then PowerShell should at least convert the incoming information to a string to provide meaningful output. Compare with findstr: if you pipe the above to findstr.exe, exactly that will happen and it will implicitly convert with | out-string -stream for findstr (and all other external / non-PowerShell programs) and so gci env:* | findstr "Pro" (on a PowerShell console!) gives you rational output. select-string is a string-manipulation tool so I find the idea that people are not thinking right about it for expecting a string-manipulation tool to manipulate the incoming information as a string to be unfair on users. PowerShell is an incredibly versatile language but I think this is a common area of confusion. Hopefully, future versions of select-string will operate in the above fashion as a result of the change request on GitHub, but in the meantime, just use | out-string -stream and it will all work as expected, including for other string manipulations which you can then deal with easily:
(gci env:* | sort name | out-string -stream) -replace "Pro", "XXX" | select-String "XXX"
to keep this short: Your approach doesn't work in PowerShell. All you need to do is
# Short Version
gci env: | ? Name -match "PG" | sort Name
# Long Version
Get-ChildItem -Path env: |
Where-Object -FilterScript { $_.Name -match "PG" } |
Sort-Object -Property Name
Select-String works fine with string content piped one by one instead of a big stream.
Cheers

Pipe to Out-GridView and Out-File got different rows?

The following command returns only one row (the parameter -Context 10 is ignored.)
select-string -path file.txt -pattern "..." -Context 10 | Out-GridView
However, the following command create a file with all the lines.
select-string -path file.txt -pattern "..." -Context 10 | Out-File file2
Why there is a difference?
This is because Out-Gridview consumes the entire MatchInfo object that Select-String outputs, and displays all of the properties of that object as columns. Out-File on the other hand basically performs the ToString() method on everything before it outputs it to a file, and for that kind of object when it converts to a string it outputs the line, and the context lines as well. If you want Out-GridView to do that you will have to pipe to Out-String and then to Out-Gridview.

PowerShell Out-file manipulation

i hope someone can help.
I am trying to manipulate a file created by powershell.
I managed to get to the end result that i want, but i am sure it would be easier if it was only one command.
# Invoke the Exchange Snapping ( make sure you are Exchange Admin to do it SO)
add-pssnapin Microsoft.Exchange.Management.PowerShell.E2010
#Create a file with list of DL in the organization
Get-DistributionGroup | Select-Object Name | Out-File C:\Pre_DLGroups.txt
$content = Get-Content C:\Pre_DLGroups.txt
#Remove the 3 first lines of the file that you dont need it
$content | Select-Object -Skip 3 | Out-file C:\DLGroups.txt
#Trim the space in the end and crate the Final file
Get-Content C:\DLGroups.txt | Foreach {$_.TrimEnd()} | Set-Content c:\FinalDLGroup.txt
is that way to make the end result in a single file rather than creating 3?
cheers
Elton
You can send your content across the pipeline without writing it out to files. You can use parenthesis to group the output of certain sets of cmdlets and/or functions, and then pipe that output through to the intended cmdlets.
This can all be applied on a single line, but I've written it here on multiple lines for formatting reasons. The addition of Out-String is something of a safety measure to ensure that whatever output you're intending to trim can actually be trimmed.
Since we're not getting this content from a text file anymore, powershell could possibly return an object that doesn't understand TrimEnd(), so we need to be ready for that.
(Get-DistributionGroup | Select-Object Name) |
Out-String |
Select-Object -Skip 3 |
Foreach {$_.TrimEnd()} |
Set-Content c:\FinalDLGroup.txt
However, an even smaller solution would involve just pulling each name and manipulating it directly. I'm using % here as an alias for Foreach-Object. This example uses Get-ChildItem, where I have some files named test in my current directory:
(Get-ChildItem test*) |
% { $_.Name.TrimEnd() } |
Set-Content c:\output.txt
Get-DistributionGroup |
Select-Object -ExpandProperty Name -Skip 3 |
Set-Content c:\FinalDLGroup.txt

Filter the output of a command as if it was text

I have a simple question, but I am also a beginner in PowerShell. I think it has to do with the fact that the output of the Get-Process command (alias ps) is objects and not text.
I want to get a list of the services running that have the name "sql" in them.
This is what I tried so far, but every attempt returns nothing:
Get-Service | where {$_ -match 'sql'}
Get-Service | where {$_ -like 'sql'}
Get-Service | Select-String sql
I am looking for a pattern that lets me treat the output of every command as searchable text.
Just forget it :o)
Outputs are objects. You are right, and you are going to use this.
So mjolinor has the shortest answer, but for your knowledge just test:
Get-Service | Get-Member
So you will understand that
Get-Service | Where-Object {$_.name -match ".*sql.*" }
also works, and there you've got your text as a property of the object.
Most answers here focus on finding the service name with "sql" in the name, not on filtering the entire output as if it was text. Also, the accepted answer uses a non-PowerShell function, "findstr".
So, granted, what follows is not the most elegant solution, but for sake of completeness I would like to provide the 100% PowerShell solution that takes the question of the OP literally:
(get-Service | Out-String) -split "`r`n" | Select-String sql
We need Out-String, because using the solutions provided in other answers doesn't provide us the full text output of the Get-Service command, only the Name parameter.
We need to split on newlines, because Select-String seems to treat the entire text as one long string, and returns it as a whole, if "sql" is found in it.
I use Select-String instead of findstr, because findstr is not a PowerShell function.
This is a purist answer, and in practice, for this specific use-case, I would not recommend it. But for people coming here through Google Search based on the question title, this is a more accurate answer...
Get-Service | Select-String -Pattern "sql"
This works just like grep. And you can even sort:
Get-Service | Select-String -Pattern "sql" | sort
The other answers are right of course about your specific question of starting services that have "sql" in their name, but to answer the generic question:
You can do Get-Service | Out-String, and you will get the output as string, much like how Unix commands work.
Also when the output is piped to non-PowerShell commands, it does get converted to text, so for example: Get-Service | grep sql would work the way you wanted.
But again, like #JPBlanc says, it is good embrace the way PowerShell works, which is that the outputs are objects. It gives you way more control and keeps things simple and readable (the Unix commands with sed, awk and what not operating on text output of other command outputs can get very cryptic!).
You're working way too hard at it:
Get-Service *sql*
If anyone wants more information on logical operations, please see Using the Where-Object Cmdlet:
• -lt -- Less than
• -le -- Less than or equal to
• -gt -- Greater than
• -ge -- Greater than or equal to
• -eq -- Equal to
• -ne -- Not equal to
• -like - Like; uses wildcards for pattern matching
Get-Service | where {$_ -match 'sql'} would be Get-Service | where {$_ -eq "sql"}
Get-Service | where {$_ -like 'sql'} would be Get-Service | where {$_ -like "sql"}
And now an actual example.
PS C:\> Get-Service | where {$_.name -like "net*"}
Status Name DisplayName
------ ---- -----------
Running Net Driver HPZ12 Net Driver HPZ12
Running Netlogon Netlogon
That the text of the name is a property of the object is important to get your head around, and how to use the property values in a filter.
Another aspect of PowerShell you can leverage to solve this is selecting properties out of objects with Select-Object (alias select):
Get-Service | select -expand name
will get you a string array with the names of the servers, and two of your original three filters would work on that. The -like isn't going to work, because there's no wildcards in the test string. The only thing it will ever match is just 'sql'.
I still believe the first solution I posted is best. It's important to know how to do late filtering, but also how to use early filtering when you can.
If you want to list all services with "sql" in the service name, just use:
get-service -name *sql*
You probably want this:
Function Select-ObjectPropertyValues {
param(
[Parameter(Mandatory=$true, Position=0)]
[String]
$Pattern,
[Parameter(ValueFromPipeline)]
$input
)
$input | Where-Object {($_.PSObject.Properties | Where-Object {$_.Value -match $Pattern} | Measure-Object).count -gt 0} | Write-Output
}
Here we are going though each property of an object to see if it matches the given pattern. If the object contains one or more such properties, we write it out. End result: grep by all properties of an object.
Put it in your configuration files and grep to your heart's content.
how about:
Get-Service| Out-String -stream | Select-String sql
where the key point is that -stream option converts the Out-String output in separate lines of text.