With -quiet, it returns $true or $false (depending on whether the input-line matched the pattern).
With -raw (which was introduced with PowerShell 7), the cmdLet returns the matched strings as string objects.
By default, select-string tries to match with regular expressions. In order to match a substring (for example to improve performance), the -simpleMatch option needs to be given.
By default, PowerShell 7 highlights the matched string. To turn this off, the -noEmphasis parameter must be specified.
Prior versions don't have the built-in capabilities to hightlight matched strings.
Common usages
Find lines in current directory that contain pattern.
Unfortunately, select-string pattern * throws an error message if select-string pattern * is executed in a directory that contains sub-directories: select-string : The file P:\ath\to\subdirectory cannot be read: Access to the path 'P:\ath\to\subdirectory' is denied.
Therefore, it is advisable to use a pipeline that pipes the result of get-childItem into the select-string cmdLet;
get-childItem * | select-object pattern
Use -list to report only the first occurence of a found pattern;
get-childItem * | select-string -list pattern
Show filenames only. filename is a property of the returned MatchInfo objects:
Similarly, such a pipeline can also be used to find numbers that have at least two digits:
42, 128, 1, 44 | select-string \d\d
Selecting lines in files
With the -path option, select-string searches for text in files, line by line:
select-string -path .\*.txt 'regexp'
Whe using select-string on files, the output includes the name of the file and the line number where the text was found:
bar.txt:603:quod erat
foo.txt:109:demonstrandum
foo.txt:721:etc etc etc
Selecting objects with specific property values (-inputObject parameter)
The following object creates an array of psCustomObjects and then uses the -inputObject option of select-object to find the property-values of the property val_2 that contain the letter a:
This approach also works on non-psCustomObjects. The following example pipes the result of get-winEvent into select-object to find messages that contain the word failed.
The -context option takes an array of one or two integers that specify how many lines before and after a matched line should be displayed (and thus provides the functionality that grep offers with its -A, -B and -C options).
Display two lines before and two lines after the matched string:
get-childItem -recurse -include *.sql | select-string from -context 2
Display one line before and two lines after the matched string:
get-childItem -recurse -include *.sql | select-string from -context 1,2
In the displayed result, a leading greater than (>) indicates the line that actually matched:
dir-one\abc.sql:4: sal.amount
> dir-one\abc.sql:5:from
dir-one\abc.sql:6: sales sal join
dir-one\abc.sql:7: customer cus on sal.cust_id = cus.id;
dir-two\dir with spaces\def.sql:7: t2.baz
> dir-two\dir with spaces\def.sql:8:from
dir-two\dir with spaces\def.sql:9: t1 left join
dir-two\dir with spaces\def.sql:10: t2 on t1.id = t2.id_1;
Simulating the Linux strings functionality
The following example tries to approximately simulate the Linux strings shell command.
The task I have given myself is to extract the words with excactly 5 letters from the following file (named text):
one two three
four five six
seven eight nine
ten elevent twelve.
{5} specifies to match the previous atom exactly five times
select-string is given the -allMatches option because there are lines where this pattern matches multiple times and I want to capture them all.
The result of this select-string operation is processed in a foreach statement that iterates over each line that matched at least once. This line is assigned to $matchedLine.
In order to find the matched words, another foreach statement that iterates over $matchedLine.matches and assigns each match to $matchedWord.
Finally, the line number and the matched word can then be printed:
1: three
3: seven
3: eight
Recursive search for a pattern (grep -R)
The following pipeline tries to demonstrate how select-string, in conjunction with get-childItem might be used to recursively search for text patterns in files that are located in and below a given directory. Thus, it sort of does what is known in the shell universe as grep -R.
get-childItem <# Get a list of files #> `
-recurse <# recursively #> `
..\.. <# start two directories further up #> `
-include '*.ps1' <# Only interested in PowerShell scripts #> |
select-string <# pipe found files into select-string #> `
'foo.*bar' ` <# find files that contain foo followed by bar #> |
format-table <# Pipe to format-table for nice output #> `
lineNumber <# We want lineNumber #> ,
@{name='rel. path' ; <# relative path #> `
expression={ resolve-path -relative $_.path }} <#(which is returned by resolve-path …) #> ,
line <# and the text of the matching line #>