Reputation: 1199
I am trying to find a pattern in files. When I get a match using Select-String
I do not want the entire line, I just want the part that matched.
Is there a parameter I can use to do this?
For example:
If I did
select-string .-.-.
and the file contained a line with:
abc 1-2-3 abc
I'd like to get a result of just 1-2-3 instead of the entire line getting returned.
I would like to know the Powershell equivalent of a grep -o
Upvotes: 70
Views: 125025
Reputation: 6999
Instead of piping to %
or select
you can use simpler .prop
Member Enumeration syntax, which magically works on multiple elements:
(Select-String .-.-. .\test.txt -All).Matches.Value
or less parentheses:
$m = Select-String .-.-. .\test.txt -All
$m.Matches.Value
Upvotes: 15
Reputation: 341
If you don't want to use ForEach operator, you can only use pipes and Select -Expand
For example, to get only the path after C:\
, you could use :
Get-ChildItem | Select-String -Pattern "(C:\\)(.*)" | Select -Expand Matches | Select -Expand Groups | Where Name -eq 2 | Select -Expand Value
Where Name -eq 2
only selects the second match of the regex pattern specified.
Upvotes: 7
Reputation: 321
None of the above answers worked for me. The below did.
Get-Content -Path $pathToFile | Select-String -Pattern "'test\d'" | foreach {$_.Matches.Value}
Get-Content -Path $pathToFile | # Get-Content will divide into single lines for us
Select-String -Pattern "'test\d'" | # Define the Regex
foreach {$_.Matches.Value} # only return the value of the Object's Matches field. (This allows for multiple result matches.)
Upvotes: 13
Reputation: 15824
In the spirit of teach a man to fish ...
What you want to do is pipe the output of your select-string command into Get-member, so you can see what properties the objects have. Once you do that, you'll see "Matches" and you can select just that by piping your output to | **Select-Object** Matches
.
My suggestion is to use something like: select linenumber, filename, matches
For example: on stej's sample:
sls .\test.txt -patt 'test\d' -All |select lineNumber,fileName,matches |ft -auto
LineNumber Filename Matches
---------- -------- -------
1 test.txt {test1, test2, test3}
2 test.txt {test3, test4}
3 test.txt {test2}
Upvotes: 16
Reputation: 202052
Or just:
Select-String .-.-. .\test.txt -All | Select Matches
Upvotes: 42
Reputation: 29479
I tried other approach: Select-String returns property Matches that can be used. To get all the matches, you have to specify -AllMatches. Otherwise it returns only the first one.
My test file content:
test test1 alk atest2 asdflkj alj test3 test
test test3 test4
test2
The script:
select-string -Path c:\temp\select-string1.txt -Pattern 'test\d' -AllMatches | % { $_.Matches } | % { $_.Value }
returns
test1 #from line 1
test2 #from line 1
test3 #from line 1
test3 #from line 2
test4 #from line 2
test2 #from line 3
Select-String at technet.microsoft.com
Upvotes: 35
Reputation: 11255
David's on the right path. [regex] is a type accelerator for System.Text.RegularExpressions.Regex
[regex]$regex = '.-.-.'
$regex.Matches('abc 1-2-3 abc') | foreach-object {$_.Value}
$regex.Matches('abc 1-2-3 abc 4-5-6') | foreach-object {$_.Value}
You could wrap that in a function if that is too verbose.
Upvotes: 40
Reputation: 3340
You can use the System.Text.RegularExpressions namespace:
http://msdn.microsoft.com/en-us/library/system.text.regularexpressions.regex.aspx
Upvotes: 2