Generate procedural command in batch file

Viewed 67

So when you use a batch file to search for substrings in a text file you could use something like the following:

:SearchOne
findstr %~1 %~2 >> output.txt
exit /b 0

If you have multiple search parameter (which all have to match...) you could use:

:SearchTwo
findstr %~1 %~2 | findstr %~3 >> output.txt
exit /b 0 

How can I search for multiple numbers of search keys whose numbers aren't fix?

like for example:

for 3: findstr %~1 %~2 | findstr %~3 | findstr %~4 >> output.txt

for 4: findstr %~1 %~2 | findstr %~3 | findstr %~4 | findstr %~5 >> output.txt

and so on...?

3 Answers

Batch files make it almost impossible to build up a pipeline in an environment variable. It is certainly possible to do it by passing the results through temporary files. Note that I'm ASSUMING you want the file names first, as in multifind *.cpp word1 word2 word3. The way you had it would require you to write that multifind word1 *.cpp word2 word3, which seems unnatural.

@echo off
findstr %2 %1 > t001
shift
shift

if "%1" == "" goto doit
:loop
findstr %1 t001 > t002
del t001
ren t002 t001
shift
if not "%1" == "" goto loop

:doit
type t001
del t001

In the following script, the first argument is considered as the file to be searched:

@echo off
setlocal EnableDelayedExpansion
set "FILE=" & set "SEARCH="
rem /* Get file name from the very first command line argument; moreover,
rem    put together a space-separated list of quoted search expressions: */
for %%A in (%*) do if defined FILE (set SEARCH=!SEARCH! "%%~A") else set "FILE=%%~A"
rem // Search the file for one expression at a time and overwrite it in each iteration:
if defined SEARCH for %%S in (!SEARCH!) do (
    findstr "%%~S" "!FILE!" > "!FILE!.tmp" & move /Y "!FILE!.tmp" "!FILE!" > nul
)
endlocal

This is not absolutely safe, some argument strings could cause syntax errors.

This very simple method works fine when the search strings have no quotes, like in your example:

@echo off
setlocal

for /F "tokens=1,2*" %%a in ("%*") do set "string1=%%b" & set "rest=%%a %%c"
findstr "%string1%" "%rest: =" | findstr "%" >> output.txt

In order to appreciate the trick used here, remove the @echo off line and run the program. An example is shown below:

C:\Tests> multifind.bat file.txt one two three four

C:\Tests> findstr "one" "file.txt"   | findstr "two"   | findstr "three"   | findstr "four"  1>>output.txt
Related