Refactored Codes
How to search files for a matching string in Windows using Powershell, How to grep in Windows
In linux and linux like OS, we have a command grep, which allows us to find string in a text file. Similarly, is there anything like that in Powershell?? Yes, there is. We can use Select-String command to achieve that, and we can do much more with this command, which can not be done with Grep. You can watch me executing commands provided in this article, on youtube. [embed]https://youtu.be/XOMhOc8BZd8[/embed]   Select-String allows you to search in strings coming in the pipeline. It supports following parameters.
  1. -SimpleMatch
  2. -Pattern
  3. -NoMatch
  4. -NoEmphasis
  5. -CaseSensitive
  6. -Raw
  7. -Path
  8. -AllMatch
I am going to start with -SimpleMatch parameter. In below given code, I am searching over list of strings, to find words that contains "Anu"
"Anurag", "Ajey", "Ajeeth" | select-string -SimpleMatch "Anu"
Output Select words containing Anu in the list of words, supplied by pipeline My search, returns me one result, because there is only one word containing Anu as it's substring. I can change the -SimpleMatch value and I will get different result. I can change the search parameter, and I will get different result.
"Anurag", "Ajey", "Ajeeth" | select-string -SimpleMatch "Aj"
Output Select words containg "Aj", from list of words coming from pipeline. When, I search for Aj , I get two matching words, because there are two words with Aj as it's substring. The above commands run on strings coming from pipeline, but the Select-String can also search on a file. Let us create a test file for searching. Run the below mentioned command to get the output of Get-Command in a text file.
Get-Command | Out-File -FilePath commands.txt
I have attached a screenshot, verifying the existence of the new file. And, also showing the sample contents of the file. Suppose, I as asked to find all the Aliases, then I can do a -SimpleSearch for Alias on the file.
select-string -path .\commands.txt -SimpleMatch "Alias"
It gives me all the lines, which has 'Alias' word in it. Suppose, I want to search for Alias, Cmdlets or functions, which does 'Find' Operation. I can run the below command, and that gives me the result.
select-string -path .\commands.txt -SimpleMatch "Find-"
Here is the output. A question comes to mind, Can we search for lines which does not match the given strings? Yes we can. Let us create a test file Event.log for that. I am creating this file in a way, it mimics a Log file.
Warning : Here is Warning... Serious Warning
Warning : Not Serious Warning
Info : just some information.
Error : Some Error has Occurred.
Errror : Error Number 2
Info : Second Information..
info : can we get better information
It has errors, warnings and info lines. Suppose, we are asked to show all the log lines which has error in it.
select-string -Path Event.log -SimpleMatch "Error"
Then we get following result. So, we got the file name, with line numbers. And, it also highlights the part of the line, which contains the "Error" word. Suppose we want the lines which are does not contain "Error" word. We want to filter out error lines. We have to add a switch parameter -NotMatch.
select-string -Path Event.log -SimpleMatch "Error" -NotMatch
Here is the output, where we get the lines, which does not contain the word Error in it. Going back to the get the matching lines. You can see that there more than one matching word, but only the first word gets highlighted. To highlight all the matching substrings, we have to use -AllMatches and -Pattern. Note :- The -AllMatches does not work with -SimpleMatch. So, to highlight all the substrings containing Warning word, we can run the below command.
select-string -Path Event.log -Pattern "Warning" -AllMatches
Here is the output, here you can see all matching substrings have been highlighted. Suppose, I want to restrict the search to matching cases, currently our search is Case-Insensitive. We can use -CaseSensitive Parameter for that. Let me show you an example, here I am searching for all the logs, which are of Information type.
select-string -Path Event.log -Pattern "Info" -AllMatches
It gives me all the lines, where it finds the word "Info".  If you look at screenshot, you can see at line number 7 , the info does not match case with Info. To filter out such matches, we can use -CaseSensitive parameter. In the output, you can see the info with smallcap is not displayed. There are two more parameters, that we can use, but is not used much. -Raw parameter returns matches as string, normally Select-String returns an object of MatchInfo. As the returned type is string, these matches does not get highlighted in the commandline. As, there are no informations of matching line numbers and index ranges and File Names.
PS D:\LearningPowerShell> select-string -Path Event.log -Pattern "Info" -AllMatches -CaseSensitive
PS D:\LearningPowerShell> select-string -Path Event.log -Pattern "Info" -AllMatches -CaseSensitive -Raw
You can see the difference in the output, where I run the command without and with -Raw parameter -NoEmphasis can also be used to turn off the highlighting.
PS D:\LearningPowerShell> select-string -Path Event.log -Pattern "Info" -AllMatches -CaseSensitive
PS D:\LearningPowerShell> select-string -Path Event.log -Pattern "Info" -AllMatches -CaseSensitive -NoEmphasis
Unlike -Raw, the return type is still MatchInfo. But, the matching substring is not highlighted by the command line. you can see the difference in the output.