1

This must be a silly question but I can't find the answer out there.. I am using Windows Grep.

I want to find the file that contains any where String1 AND string2 AND String3

Thank you!

EDIT

I've tried a regex from this answer but the windows grep shows up an error..

(?=match this expression)(?=match this too)(?=oh, and this)

EDIT 2:

Thank you @brianadams and @MC ND for your answers! I´ll check out awk as it seems a good alternative to windows grep. As the question is about windows grep I think the best is to leave it open to check out if someone knows the answer..

Again thank you very much for your answers!

Community
  • 1
  • 1
Daniel
  • 1,189
  • 2
  • 12
  • 30
  • 2
    I haven't used grep in a while by my approach would probably be to do 3 separate greps, then get the intersect of the results. – kschieck Jan 10 '14 at 20:44
  • That's sound right! The only problem is that first, there are a few dozens of files on the results and second and more important, I am too lazy.. :D Now, seriously it's something I will have to do a lot in the future and it would be cool to do it programatically! Thank your for your answer I'll use it if no one gives a better answer.. Thanks! – Daniel Jan 10 '14 at 20:52
  • Maybe this will help you(scroll down to AND): http://www.thegeekstuff.com/2011/10/grep-or-and-not-operators/ – kschieck Jan 10 '14 at 21:01
  • I just tried that but doesn't work.. is that not only for linux? – Daniel Jan 10 '14 at 21:10
  • It looks like it, I thought it may work with windows grep. worth a shot – kschieck Jan 10 '14 at 21:11
  • No problem! Help is always very welcome! – Daniel Jan 10 '14 at 21:13
  • @eyyo - Which "Windows grep" are you referring to. I suspect there are countless versions of grep compiled for Windows. – selbie Jan 11 '14 at 01:52
  • @selbie hello, I'm using the last one, 2.3 – Daniel Jan 13 '14 at 14:23
  • @eyyo - Googling for "Windows grep" reveals at least 5 different programs from different authors called "grep". The point I'm making it would be extremely helpful if your post identified which product you are referring to. I suspect you might be referring to the one from wingrep.com. But odds are also high you could be referring to GNU grep compiled for windows. – selbie Jan 13 '14 at 17:15
  • @selbie ok! It's the wingrep.com.. – Daniel Jan 13 '14 at 22:17

2 Answers2

2

download windows awk from here

then do this

C:\> awk "/string1/&&/string2/&&/string3/{print}" myFile.txt

better than grep or findstr

EDIT If you want to find all 3 strings anywhere in the file, pass RS="\0" to awk. This will ask awk to read in the whole file

C:\> awk "BEGIN{RS=\"\0\"}/string1/&&/string2/&&/string3/{print FILENAME;exit}" myFile.txt
brianadams
  • 233
  • 1
  • 5
  • From op question, the three substrings can happen anywhere in the file, doesn't need to be on the same line. Maybe i'm wrong, but this pattern only match the three strings on the same record. – MC ND Jan 12 '14 at 08:44
  • @MCND, piping to 3 `findstr` also will fail to find them. if OP wants to find these 3 patterns anywhere in the file, then `&&` can be changed to `||` – brianadams Jan 13 '14 at 12:44
  • No, findstr will not fail. The first findstr searchs the first string and returns the list of files that match (the /m switch, no line matches, only filenames). Second findstr searchs the second string over the files in file list that is retrieved from stdin, piped from the first findstr (the /f:/ switch), sending to next findstr in pipe the list of matching files, and the process is repeated for the third string. In your awk code, changing to `||` will not ensure the three strings are in the file, only that at least one is in the file – MC ND Jan 13 '14 at 12:56
  • yes, but if like you said, the patterns are on different lines, then the first `findstr` would only find the first pattern. isn't that so? – brianadams Jan 13 '14 at 12:59
  • Yes, but the findstr is not sending the matching lines over the pipe. Only the file names. So, second findstr retrieves the list on files (those that contains string1) in where to search for string2. And then, send the list of files found (that contains string1 and string2) do the third findstr to search the third string. The key is the fact that no data lines are in the pipe, only filenames, and that each findstr only search it string over the set of files indicated by the previous findstr. – MC ND Jan 13 '14 at 13:03
1

Usually, for complicated search conditions i recomend using grep, but in this case, searching strings all over the files, findstr can be the better option (or not, see the undocumented behaviour and limitations of findstr)

Anyway, assuming your files don't collide with findstr limitations, one of the characteristics is its ability to retrieve from console/pipe the list of files where it should search for string. So, in your case, you will need something like

findstr /l /c:"string1" /m files*.* | findstr /l /c:"string2" /m /f:/ | findstr /l /c:"string3" /m /f:/

where /l means search are literal strings, /c:"string" the string to search, /m return only the list of files, /f:/ retrieve from stdin the list of files in where to search.

That way, each findstr search only in the list of files returned from the previous findstr in the pipe.

Community
  • 1
  • 1
MC ND
  • 69,615
  • 8
  • 84
  • 126
  • this is ugly. piping to so many process. and `grep` is way better than `findstr` – brianadams Jan 12 '14 at 02:51
  • @brianadams, i agree, grep is way better, but in this case, without instaling anything aditional, findstr can do the job without temporary files that should be needed to solve it with grep. – MC ND Jan 12 '14 at 08:42
  • why would you need to create temp files with `grep`? `grep` fundamentally serve the same purpose as `findstr`. – brianadams Jan 13 '14 at 12:46
  • @brianadams, yes, but grep does not accept lists of files to be processed from stdin, so, to solve it, it is necessary to generate the temporary files with the result of each substring search to be later processed and determine the final list of files containing the three substrings – MC ND Jan 13 '14 at 12:51
  • just substitute the `findstr` above with `grep`. `grep` is able to take in globs as well as stdin. – brianadams Jan 13 '14 at 12:55
  • @brianadams, how do you indicate to `grep` that the data flowing in the pipe are filenames to process and not lines to check for matches? – MC ND Jan 13 '14 at 12:58
  • passing `-l` to `grep` will tell it to output just the filename. even if it can't take in files as stdin, its easily solvable with a for loop and you still won't need to create temp files like you said. in any case, `grep` is not my preferred answer – brianadams Jan 13 '14 at 13:12
  • another way which could be done with purely batch is a for loop over the files, then setting increment counters for each pattern found. If the counter is 3, then all 3 strings are found. – brianadams Jan 13 '14 at 13:17
  • @brianadams, first grep generates the first list. I place a loop around this list to a) call a grep command for each file (time consuming) or b) concatenate the list of files for next grep (command line length limitation). And still need to search for third string. Maybe i'm blind (not the first time) but i see no eficient way of doing it without temporary files. – MC ND Jan 13 '14 at 13:18
  • GNU linux `grep` may be passed `-zo` to simulate slurping of the whole file. coupled with `-P` (pcre) and `(?s)` for `DOTALL`, so something like this `grep -Pzo "(?s)str1.*str2.*str3" myfile` works for linux. I am not sure if this behaviour is the same on Windows version. Also provided there's a way in batch to store the whole file in a variable, that could also eliminate temp files. – brianadams Jan 13 '14 at 13:58
  • @brianadams: The gnuwin32 grep version (the most usual) indicates -P is experimental, and can not be combined with -z (--null-data). And the environment variables have a limit of 32767 characters. – MC ND Jan 13 '14 at 15:31