Being GREP like on Windows

For many years I used grep on UNIX. It’s an amazing tool, allowing you to search for text in a variety of ways across a number of files. Windows however lagged behind and if you wanted to do the same thing, you needed a specialist program because that didn’t come baked into the operating system. At least, that was the case before PowerShell.

Here, I am going to illustrate how to use some of the PowerShell commands to imitate similar functionality on Windows whilst I hunt for errors in a log file (something I have needed to do, recently).

Let’s start with what we are searching through - here’s a small excerpt of the file I am using to give you an idea of what we will be finding. Bear in mind, however, that the real file is tens of thousands of lines long.

*INFO*: [soap/soapexe.c:4570] Built search: 0.312489 secs 0.000000 secs
*INFO*: [soap/soapexe.c:4570] Got result: 0.343741 secs 0.031252 secs
*ERROR*: [soap/soapexe.c:4890] Iexe method call failed - server shutting down
*INFO*: [soap/soapexe.c:5409] send SIGTERM to shutdown
*INFO*: [soap/soapexe.c:4570] SOAPX_SR_open_db: acct@<u>localhost:2413:d:/data/index/dbs/live/db
*INFO*: [soap/soapexe.c:4570] Opened database: <u>localhost:2413:d:/data/index/dbs/live/db 0.312496 secs 0.312496 secs

So where do we begin? Well, I want to know which lines contain the string “ERROR” (line 3) above and one way of achieving that is this command:

Select-String -Path .\stdout.txt ERROR

That works well; we are searching in the file named “stdout.txt” for the string “ERROR”. Here you can see some of the results:

stdout.txt:50756:*ERROR*: [http-request.c:264] h_read failed (recv failed (No error))
stdout.txt:50757:*ERROR*: [http-server.c:688] h_new_from_socket failed (recv failed (No error))
stdout.txt:50790:*WARN\*: [http-socket.c:497] h_read failed (recv failed (No error))

Hold on, though. What about that last line? I don’t really want that, even though it does contain the desired string. Can you see the problem? It’s not being case-sensitive. To fix that, we can add another parameter.

Select-String -Path .\stdout.txt ERROR -CaseSensitive

Ah, much better - we’ve gotten rid of that warning line.

stdout.txt:50756:*ERROR*: [http-request.c:264] h_read failed (recv failed (No error))
stdout.txt:50757:*ERROR*: [http-server.c:688] h_new_from_socket failed (recv failed (No error))

I did mention that there are a few less than a bazillion lines in this file? So really, I’d like to know which line number those matches occur on. “Select-String” is going to need some help, but the information is there, we just need to uncover it.

Select-String -Path .\stdout.txt ERROR -CaseSensitive | Select-Object -Property LineNumber

Here, we’re piping the output to another command that is extracting particular properties, in this case, the line number. Run that, though, and you will see the following:

     80624
80625
80645
80646
...

And so on…(more ellipses!) That’s helpful, but really, the line number PLUS the actual line would be more useful. Only one more change to make:

Select-String -Path .\stdout.txt ERROR -CaseSensitive | Select-Object -Property LineNumber,Line

Leading to:

292402 *ERROR*: [http-server.c:688] h_new_from_socket failed (recv failed (No error))                       
292428 *ERROR*: [http-request.c:264] h_read failed (recv failed (No error))

If you need to, you can find more information on the Select-String and Select-Object commandlets at the excellent MS docs website.

Happy searching.


Hi! Did you find this useful or interesting? I have an email list coming soon, but in the meantime, if you ready anything you fancy chatting about, I would love to hear from you. You can contact me here or at stephen ‘at’ logicalmoon.com