PowerShell Select-String
File and stream text search with Select-String — the PowerShell grep equivalent.
Select-String Quick Reference (PowerShell grep)
Select-String -Path *.log -Pattern "ERROR"
Select-String -Path *.log -Pattern "ERROR" -CaseSensitive
Get-ChildItem -Recurse -Filter *.adoc | Select-String -Pattern "hardcoded"
Select-String -Path auth.log -Pattern "Failed" -Context 2,3
# 2 lines before, 3 lines after
Get-Content log.txt | Select-String -Pattern '\d+\.\d+\.\d+\.\d+' -AllMatches |
ForEach-Object { $_.Matches.Value } | Sort-Object -Unique
Select-String -Path *.log -Pattern "ERROR", "FATAL", "CRITICAL"
Select-String -Path config.txt -Pattern "^#" -NotMatch
# Lines NOT starting with #
Get-ChildItem -Recurse -Include *.ps1, *.psm1 |
Select-String -Pattern "Invoke-Command" |
Select-Object Path, LineNumber, Line
Select-String -Path *.log -Pattern "Failed login from (?<ip>\d+\.\d+\.\d+\.\d+)" |
ForEach-Object { $_.Matches.Groups['ip'].Value } |
Group-Object | Sort-Object Count -Descending | Select-Object -First 10
# Top 10 source IPs for failed logins — structured, not text
Select-String (PowerShell grep)
Basic Search
Select-String -Path *.log -Pattern "ERROR"
Select-String -Path *.log -Pattern "ERROR" -CaseSensitive
Get-ChildItem -Recurse -Filter *.adoc | Select-String -Pattern "hardcoded"
sls "Failed" auth.log
gci -r -fi *.log | sls "ERROR"
Context & Surrounding Lines
Select-String -Path auth.log -Pattern "Failed" -Context 2,3
# 2 lines before, 3 lines after
Select-String -Path config.txt -Pattern "error" -Context 5,0
Pattern Extraction
Get-Content log.txt | Select-String -Pattern '\d+\.\d+\.\d+\.\d+' -AllMatches |
ForEach-Object { $_.Matches.Value } | Sort-Object -Unique
Select-String -Path *.log -Pattern "Failed login from (?<ip>\d+\.\d+\.\d+\.\d+) user (?<user>\w+)" |
ForEach-Object {
[PSCustomObject]@{
IP = $_.Matches.Groups['ip'].Value
User = $_.Matches.Groups['user'].Value
File = $_.Filename
Line = $_.LineNumber
}
} | Format-Table
Get-ChildItem -Recurse -Filter *.log | ForEach-Object {
$count = (Select-String -Path $_.FullName -Pattern "ERROR" -SimpleMatch).Count
if ($count -gt 0) { [PSCustomObject]@{File=$_.Name; Errors=$count} }
} | Sort-Object Errors -Descending
Invert & Filter
Select-String -Path config.txt -Pattern "^#" -NotMatch
Select-String -Path *.log -Pattern "ERROR|WARN|CRITICAL"
Select-String -Path app.log -Pattern "ERROR" |
Where-Object { $_.Line -notmatch "expected|timeout|retry" }
Pipeline Power (what bash grep can’t do)
Select-String -Path auth.log -Pattern "Failed.*from (?<ip>\d+\.\d+\.\d+\.\d+)" |
ForEach-Object { $_.Matches.Groups['ip'].Value } |
Group-Object | Sort-Object Count -Descending |
Select-Object -First 10 Name, Count
Get-ChildItem -Recurse -Filter *.log |
Select-String -Pattern "(?<ts>\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}).*ERROR.*(?<msg>.*)" |
ForEach-Object {
[PSCustomObject]@{
Timestamp = $_.Matches.Groups['ts'].Value
Message = $_.Matches.Groups['msg'].Value
File = $_.Filename
}
} | Export-Csv -Path errors.csv -NoTypeInformation
Get-Content -Path app.log -Wait -Tail 0 | Select-String -Pattern "ERROR|CRITICAL"
Network Forensics
Get-WinEvent -LogName Security -MaxEvents 1000 |
Where-Object { $_.Id -eq 4625 } |
ForEach-Object { $_.Message } |
Select-String -Pattern "Account Name:\s+(\S+)" -AllMatches |
ForEach-Object { $_.Matches.Groups[1].Value } |
Group-Object | Sort-Object Count -Descending | Select-Object -First 10
Get-Content output.txt |
Select-String -Pattern '\b(?:\d{1,3}\.){3}\d{1,3}\b' -AllMatches |
ForEach-Object { $_.Matches.Value } | Sort-Object { [version]$_ } -Unique
# Search a switch config dump for common issues
$config = Get-Content switch-config.txt
$config | Select-String -Pattern "permit any any|no service password|telnet|enable password"
Comparison: bash grep vs PowerShell
| Task | bash | PowerShell |
|---|---|---|
Basic search |
|
|
Recursive |
|
|
Count |
|
|
Extract IPs |
|
|
Context |
|
|
Invert |
|
|
Top talkers |
|
|
Files only |
|
|
Real-time |
|
|
The PowerShell advantage: every match is an object with .Filename, .LineNumber, .Line, .Matches, .Matches.Groups. You can pipeline into Group-Object, Sort-Object, Export-Csv, ConvertTo-Json — no awk required.