3

I want to find any file that can match two regular expressions, for example all files that have at least one of bat, hat, cat as well as the word noun. That would be any file that can match both regular expressions [bhc]at and noun.

The regex parameter to select-string only seems to work on a line-by-line basis. It seems you can pass in multiple patterns delimited by commas (select-string -pattern "[bhc]at","noun") but it matches either, rather than both.

Lance U. Matthews
  • 15,725
  • 6
  • 48
  • 68
tenpn
  • 4,556
  • 5
  • 43
  • 63

4 Answers4

5

You can always just use two filters:

dir | ? {(gc $_) -match '[bhc]at'} | ?{(gc $_) -match 'noun'}

This just gets all the objects that match the first criteria, and checks that result set for the second. I imagine it would be quicker than checking both as well since a lot of files will only get checked once, then filtered out.

JNK
  • 63,321
  • 15
  • 122
  • 138
3

Here's a one that only requires one get-content:

dir | where-object{[string](get-content $_)|%{$_ -match "[bhc]at" -and $_ -match "noun"}}
mjolinor
  • 66,130
  • 7
  • 114
  • 135
2

Merging @mjolinor's single get-content with @JNK's optimised filtering gives:

dir | ?{ [string](gc $_) | ?{$_ -match "[bhc]at"} | ?{$_ -match "noun"} }

If you don't mind the repetition, you can pipe the results to select string to view the contexts of these matches:

    | select-string -pattern "[bhc]at","noun" -allmatches
tenpn
  • 4,556
  • 5
  • 43
  • 63
  • Are you sure you don't need both get-contents? The second match appears to work against the filename. – TrueWill Nov 12 '13 at 22:17
0

I have come up with the rather cumbersome-but-working:

dir | where-object{((get-content $_) -match "[bhc]at") -and ((get-content $_) -match "noun")}

I can shorten this with aliases, but is there a more elegant way, preferably with less keystrokes?

My other option, if this becomes a frequent problem, seems to be making a new commandlet for the above snippet.

tenpn
  • 4,556
  • 5
  • 43
  • 63