Comparison of the lines with batch - batch-file

I want to compare the first column of before.txt with the first column of after.txt line per line ( the first with the first,the second with the second and so on).
As output now I get only the last value E992A84B8C8A1FEF3B94242403D5D84B two times. My question is how to compare all the lines and get the result message?
FOR /F "tokens=1 delims= " %%G IN (before.txt) DO set variable1=%%G
FOR /F "tokens=1 delims= " %%I IN (after.txt) DO set variable2=%%I
echo !variable1!
echo !variable2!
if /I !variable1!==!variable2! (
echo !variable1! !variable2! md5sum check is ok
)
after.txt
94F948D2615318505FD84D722A6F5F4F U:\testbmbf\0012\F96B1522A\MASTER\00000001.tif
4F5022E3290A9A8A4E8905C5CAAFB1A6 U:\testbmbf\0012\F96B1522A\MASTER\00000002.tif
776DF4069AD1914D9C37593E423BC0E4 U:\testbmbf\0012\F96B1522A\MASTER\00000003.tif
95EC963E9C789B3502E1E2C85E505218 U:\testbmbf\0012\F96B1522A\MASTER\00000004.tif
D5DD98F880A7204092EAA9355A4B558B U:\testbmbf\0012\F96B1522A\MASTER\00000005.tif
1A08F9B01904F3EF689B44093343AE2C U:\testbmbf\0012\F96B1522A\MASTER\00000006.tif
437DC62245852A01CCF4F2689F82920E U:\testbmbf\0012\F96B1522A\MASTER\00000007.tif
A4E7C76EC523F1E2799BE8CE049D28FC U:\testbmbf\0012\F96B1522A\MASTER\00000008.tif
177689553B9D9392AD6B72130EE1D22F U:\testbmbf\0012\F96B1522A\MASTER\00000009.tif
EB0F2F741428CF376909AB65BEF6659F U:\testbmbf\0012\F96B1522A\MASTER\00000010.tif
E992A84B8C8A1FEF3B94242403D5D84B U:\testbmbf\0012\F96B1522A\MASTER\00000011.tif
before.txt
94F948D2615318505FD84D722A6F5F4F U:\testbmbf\0012\F96B1522A\00000001.tif
4F5022E3290A9A8A4E8905C5CAAFB1A6 U:\testbmbf\0012\F96B1522A\00000002.tif
776DF4069AD1914D9C37593E423BC0E4 U:\testbmbf\0012\F96B1522A\00000003.tif
95EC963E9C789B3502E1E2C85E505218 U:\testbmbf\0012\F96B1522A\00000004.tif
D5DD98F880A7204092EAA9355A4B558B U:\testbmbf\0012\F96B1522A\00000005.tif
1A08F9B01904F3EF689B44093343AE2C U:\testbmbf\0012\F96B1522A\00000006.tif
437DC62245852A01CCF4F2689F82920E U:\testbmbf\0012\F96B1522A\00000007.tif
A4E7C76EC523F1E2799BE8CE049D28FC U:\testbmbf\0012\F96B1522A\00000008.tif
177689553B9D9392AD6B72130EE1D22F U:\testbmbf\0012\F96B1522A\00000009.tif
EB0F2F741428CF376909AB65BEF6659F U:\testbmbf\0012\F96B1522A\00000010.tif
E992A84B8C8A1FEF3B94242403D5D84B U:\testbmbf\0012\F96B1522A\00000011.tif

Aschipl's batch tweaked to your requirements:
:: Q:\Test\2018\04\27\SO_50067394.cmd
#echo off
setlocal EnableExtensions EnableDelayedExpansion
set "FILE1=after.txt"
set "FILE2=before.txt"
:: set "RET=Comparison.txt" & rem // (none to output to console)
if not defined RET set "RET=con"
for /F %%C in ('^< "%FILE1%" find /C /V ""') do set "NUM1=%%C"
4< "%FILE1%" 3< "%FILE2%" > "%RET%" (
for /L %%I in (1,1,%NUM1%) do (
set "LINE1="
0<&4 set /P "LINE1="
set "LINE2="
0<&3 set /P "LINE2="
if not ErrorLevel 1 If "!LINE1:~0,32!"=="!LINE2:~0,32!" echo(!LINE1:~0,32! !LINE2:~0,32! md5sum check is ok
)
)
endlocal
exit /B
Sample output:
> Q:\Test\2018\04\27\SO_50067394.cmd
94F948D2615318505FD84D722A6F5F4F 94F948D2615318505FD84D722A6F5F4F md5sum check is ok
4F5022E3290A9A8A4E8905C5CAAFB1A6 4F5022E3290A9A8A4E8905C5CAAFB1A6 md5sum check is ok
776DF4069AD1914D9C37593E423BC0E4 776DF4069AD1914D9C37593E423BC0E4 md5sum check is ok
95EC963E9C789B3502E1E2C85E505218 95EC963E9C789B3502E1E2C85E505218 md5sum check is ok
D5DD98F880A7204092EAA9355A4B558B D5DD98F880A7204092EAA9355A4B558B md5sum check is ok
1A08F9B01904F3EF689B44093343AE2C 1A08F9B01904F3EF689B44093343AE2C md5sum check is ok
437DC62245852A01CCF4F2689F82920E 437DC62245852A01CCF4F2689F82920E md5sum check is ok
A4E7C76EC523F1E2799BE8CE049D28FC A4E7C76EC523F1E2799BE8CE049D28FC md5sum check is ok
177689553B9D9392AD6B72130EE1D22F 177689553B9D9392AD6B72130EE1D22F md5sum check is ok
EB0F2F741428CF376909AB65BEF6659F EB0F2F741428CF376909AB65BEF6659F md5sum check is ok
E992A84B8C8A1FEF3B94242403D5D84B E992A84B8C8A1FEF3B94242403D5D84B md5sum check is ok

The usual way to read several files in parallel is described at this answer and consists of read the first file via a for /F command and the other file(s) via redirected set /P command(s). For example:
#echo off
setlocal EnableDelayedExpansion
rem First file is read with FOR /F command
rem Second file is read via redirected stdin
< after.txt (for /F %%G in (before.txt) do (
rem Read next line from after.txt
set /P "variable2="
rem Compare first token of both files
for /F %%I in ("!variable2!") do (
if /I %%G==%%I (
echo %%G %%I md5sum check is ok
)
)
))
Note that the default for /F behavior is get the first token delimited by space, so "tokens=1 delims= " option is not necessary...
However, if the files are small you may use a simpler method:
#echo off
for /F "tokens=1,2 delims=: " %%F in ('findstr /N "^" before.txt') do (
for /F "tokens=1,2 delims=: " %%H in ('findstr /N "^" after.txt') do (
if %%F equ %%H if /I %%G == %%I (
echo %%G %%I md5sum check is ok
)
)
)
In this method a findstr /N "^" command is used to enumerate all lines in both files, so if %%F equ %%H command is used to synchronize (select the same) lines in both files. This method is not efficient, so it will take longer if the files are not small...

An off topic powershell answer with the same result
## Q:\Test\2018\04\27\SO_50067394.ps1
$after = Import-csv .\after.txt -delimiter ' ' -header MD5,X,FileName
$before = Import-csv .\before.txt -delimiter ' ' -header MD5,X,FileName
for ($I=0;$I -le $after.Count;$I++) {
If ($after[$i].MD5 -eq $before[$I].MD5){
"{0} {1} md5sum check is ok" -f $after[$i].MD5,$before[$I].MD5
} else {
"MD5 differs between files {0} and {1}" -f $after[$i].FileName,$before[$I].FileName5
}
}

You can set 2 counters. When the counters are equal you test the 2 columns. This way you get also the line number of the error !
#echo off
setlocal enabledelayedexpansion
set $counter1=1
for /f "delims= " %%a in (before.txt) do (
set $counter2=1
for /f "delims= " %%b in (after.txt) do (
if !$counter1!==!$counter2! (
if "%%a"=="%%b" (echo line !$counter1! cheksum OK
) else (echo line !$counter1! cheksum KO)
)
set /a $counter2+=1
)
set /a $counter1+=1
)
Output :
line 1 cheksum OK
line 2 cheksum OK
line 3 cheksum OK
line 4 cheksum OK
line 5 cheksum OK
line 6 cheksum OK
line 7 cheksum OK
line 8 cheksum OK
line 9 cheksum KO
line 10 cheksum OK
line 11 cheksum OK

Related

Removing carriage returns from a text file using a batch file based on a value

I have a text file that I would like to edit and therefore would like to remove the last line. I have the following code for this:
for /f "delims=" %%a in (input.txt) do (
echo/|set /p ="%%a%"
)>>output.txt
input:
GRUPPEA;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;
GRUPPEA;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;
GRUPPEA;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;
GRUPPEB;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;
GRUPPEB;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;
GRUPPEB;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;
output:
GRUPPEA;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;GRUPPEA;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;GRUPPEA;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;GRUPPEB;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;GRUPPEB;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;GRUPPEB;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;
Now I would like to edit the data in groups for example by the first value, so that I have the following output:
GRUPPEA;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;GRUPPEA;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;GRUPPEA;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;
GRUPPEB;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;GRUPPEB;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;GRUPPEB;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;
If I replace the FOR /F "delims=" %%a in (input.txt) do … loop with an equivalent FOR %%a in … loop:
#ECHO OFF
SETLOCAL EnableExtensions EnableDelayedExpansion
set "_gruppeName="
(
for %%a in (
"GRUPPEA;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;"
"GRUPPEA;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;"
"GRUPPEA;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;"
"GRUPPEB;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;"
"GRUPPEB;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;"
"GRUPPEB;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;"
"GRUPPEC;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;"
"GRUPPEC;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;"
"GRUPPEC;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;"
) do (
for /f "tokens=1 delims=;" %%A in ("%%~a") do (
if /I NOT "%%~A"=="!_gruppeName!" (
if defined _gruppeName echo(
set "_gruppeName=%%~A"
)
)
echo/|set /p ="%%~a"
)
echo(
)>>output.txt
REM debugging output follows
type output.txt
Output:
1st run: 2>NUL del output.txt & D:\bat\CR\61816520.bat
GRUPPEA;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;GRUPPEA;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;GRUPPEA;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;
GRUPPEB;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;GRUPPEB;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;GRUPPEB;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;
GRUPPEC;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;GRUPPEC;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;GRUPPEC;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;
Next run: D:\bat\CR\61816520.bat
GRUPPEA;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;GRUPPEA;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;GRUPPEA;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;
GRUPPEB;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;GRUPPEB;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;GRUPPEB;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;
GRUPPEC;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;GRUPPEC;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;GRUPPEC;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;
GRUPPEA;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;GRUPPEA;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;GRUPPEA;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;
GRUPPEB;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;GRUPPEB;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;GRUPPEB;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;
GRUPPEC;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;GRUPPEC;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;GRUPPEC;123;12345;sdfdsfds;sdfdsfsdfs;sdfsdfafsf;
Your question is not clear
based on ... the first value (GRUPPEA)
is it SORTed? or just write duplicates on the same line?
#echo off
SETLOCAL EnableExtensions EnableDelayedExpansion
::VARIABLES
set "in=input.txt" IN file
set "out=output.txt" OUT file
set/a"#lines=0"
set "gruppe="
set "prevContent="
::Count lines
FOR /F %%L in ('
"findstr /N "^^" "%in%" %= do not skip empty lines =%"
') do set/a"#lines+=1" %= Get the # of lines =%
::Read IN via SET /P #LINES number of times
::Bangs (!) will be lost
<"%in%" >"%out%" (FOR /L %%# in (1 1 %#lines%) do (
set "data=" ::clear DATA
set/p"data=" ::read from IN
FOR /F tokens^=1^ delims^=^;^ eol^= %%T in ("!data!") do set "gruppe=%%T"
if NOT "!prevContent!" == "!gruppe!" (
set "prevContent=!gruppe!"
echo(
)
<nul set/p"=!data!" ::does not work with leading space, tabs, or equal signs
)) %= read file by lines via SET /P =%
exit /b
The script counts the number of lines using FINDSTR /N and a FOR /F loop to count the # of lines, which is required to execute SET /P that many times.
Tips:
Use ECHO( instead of the problematic ECHO.
Using a pipe | is very slow, as described by #jeb here. Use <nul instead

Windows Batch SET Syntax

I have adopted some code from here:
Extract substring between 2 strings
Rem Looking for a test.txt substring preceded by page\[%%x\]= and succeeded by ;
#Echo Off
for /l %%x in (0, 1, 4) do (
echo %%x
For /F "Delims=" %%A In ('FindStr /I "page\[%%x\]=.*;" "test.txt"') Do Call :Sub "%%A" "%%x"
)
Pause
GoTo :EOF
:Sub
Set "Line=%~1"
Set "Up2Sub=%Line:*page[ %~2 ]=%"
Set "SubStr=%Up2Sub:;="&:"%"
Echo %SubStr% > test%~2.json
Exit /B
The issue I am having is regarding this line:
Set "Up2Sub=%Line:*page[ %~2 ]=%"
The variable %~2 does not get concatenated correctly.
What would be the syntax to get this value of the %~2 variable added to this SET statement in between the []?
Thanks
Sample text.txt
....
page[0]={*****};
page[1]={*****};
page[2]={*****};
page[3]={*****};
page[4]={*****};
....
To split a string, you can also use a for /f loop:
#Echo Off
for /l %%x in (0, 1, 4) do (
For /F "Delims=" %%A In ('FindStr /I "page\[%%x\]=.*;" "test.txt"') Do (
for /f "tokens=2 delims=;=" %%s in ("%%A") do echo %%x: %%s
)
)
Pause
This splits the string (%%A) into tokens, separated by ; and =. With page[0]={*****};, the first token is page[0],then =is a delimiter. The second token is {*****} and the third token (after the;) is empty. we just include the ';' to the delimters to get rid of it.
With a little analyzing your file and choosing tokens and delims right, you can even reduce the code to a single for:
For /F "tokens=2,4 delims=[]{}" %%A In ('FindStr /I "page\[[0-4]\]=.*;" "test.txt"') Do echo {%%B}>test%%A.json

findstr multiple search string and print each occurrence only the first line

for example i have text file with content
superman
batman
hello world
sport cars
hello world2
jackie chan
flower
supermom
hello world3
clock
fried chicken
microsoft
flower boy
flash dance
flower girl
flowerwoman
sun flower
what the hello
i want to create a batch file using findstr with multiple search string, for example: hello and flower, but i want to print only the first occurence each, in other words, it will skip the first search string and move on to search the next string. so the result will be like this:
hello world
flower
hello world3
flower boy
what the hello
is this possible? i can print all the occurence found in multiple files to output.txt with this code
#echo off
>"output.txt" (
for %%F in (*.txt) do (
findstr /c:"hello" /c:"flower" "%%F"
(echo()
)
)
findstr . "output.txt" >"output.txt.new"
move /y "output.txt.new" "output.txt" >nul
type output.txt
#echo off
setlocal EnableDelayedExpansion
set "word[0]=hello"
set "word[1]=flower"
set "lastFind="
>"output.tmp" (
for %%F in (*.txt) do (
for /F "delims=" %%a in ('findstr /c:"%word[0]%" /c:"%word[1]%" "%%F"') do (
set "line=%%a"
if not defined lastFind (
if "!line:%word[0]%=!" equ "!line!" (set lastFind=0) else set lastFind=1
)
for %%b in (!lastFind!) do for /F %%c in ("!word[%%b]!") do if "!line:%%c=!" equ "!line!" (
echo !line!
set /A "lastFind=(lastFind+1)%%2"
)
)
rem Activate next line to restart the seek in each file
REM set "lastFind="
)
)
ren output.tmp output.txt
type output.txt
#echo off
setlocal enableDelayedExpansion
set "MATCH1=hello"
set "MATCH2=flower"
>"output.txt" (
for %%F in (*.txt) do if not %%~nxF==output.txt (
set matchIndex=0
set expectedMatch=%MATCH1%
for /f "delims=" %%a in ('findstr /c:"%MATCH1%" /c:"%MATCH2%" "%%F"') do (
echo %%a | find "!expectedMatch!" >nul
if !matchIndex!==0 (
set matchIndex=1
if errorlevel 1 set matchIndex=2 & ver>nul
)
if not errorlevel 1 (
echo %%a
set /a matchIndex=!matchIndex! %% 2 + 1
call set "expectedMatch=%%MATCH!matchIndex!%%"
)
)
)
)
type output.txt
pause
Currently the expected match index is reset to the first search string each new *.txt file, so in case you want a continuous alteration of strings between files simply move set matchIndex=1 before the first loop.

Could batch file recognize the fields in the cfg file?

I have cfg file which has two fields : test.cfg
[Test_1] = 12345
TC_1=testCase/String_print.tc -arg "Indonesia" -logToConsole
TC_2=testCase/test2.tc -c "ramen" -logToConsole
[Test_2] = 12346
TC_1= testCase/test.tc -c "olleH" -logToConsole
And bat file test.bat
#ECHO off
set var=C:\Users\syuniyar\.EasyTest\4\ccl\config\test2.cfg
SETLOCAL enabledelayedexpansion
FOR /F "tokens=*" %%a IN (%var%) DO (
SET line=%%a
IF "!line:~0,7!"=="Test_1=" SET Test_1=!line:~7! (
FOR /F "tokens=*" %%a IN (%var%) DO (
IF "!line:~0,5!"=="TC_1=" SET TC_1=!line:~5!
IF "!line:~0,5!"=="TC_2=" SET TC_2=!line:~5!
)
)
)
SET TC_1=%TC_1:;=%
SET TC_2=%TC_2:;=%
ECHO %TC_1%
ECHO %TC_2%
I want to retrieve the TC_1 in Test_1 = 12345 which has the value 'testCase/String_print.tc -arg "Indonesia" -logToConsole'. But from the current code what I got is 'testCase/test.tc -c "olleH" -logToConsole' which is from 12346. It returns the last item matched. My questions are : Is it possible that batch file recognizes something like Test_1\TC_1? Before I tried using array but it stored all the element from cfg file into one single array.
Could anyone help?
This Batch file do what you requested:
#echo off
setlocal EnableDelayedExpansion
rem Get the line number of "[Test_1]"
for /F "delims=:" %%a in ('findstr /N /L /B "[Test_1]" test2.cfg') do set lines=%%a
rem Get the TC_1 line after previous one
for /F "skip=%lines% tokens=1,2 delims==" %%a in (test2.cfg) do (
if "%%a" equ "TC_1" set "%%a=%%b" & goto continue
)
:continue
echo TC_1=%TC_1%

copy lines from a text file to another

i have two text files
file1 has the following lines
line1
line2
hello-hai-1
hello-2-hai
3-hai-hello
hello
and file 2 has
line4
line3
hello-hai-5
hello-7-hai
6-hai-hello
hai
hello-4
what i want to do is copy all the lines which contain both hello and hai in file2 and overwrite it on those lines in file1, the no. of lines may or may not be equal. but all the hello-hai lines are together in both files
the current code i use is
setlocal enabledelayedexpansion
for /f "tokens=1*delims=:" %%i in ('^<file2 essentials\findstr.exe /n "hello"') do set "#%%i=%%j"
(for /f "delims=" %%i in (file1) do (
set "line=%%i"
if not "!line!"=="!line:hello=!" (
if not "!line!"=="!line:hai=!" (
if not defined flag (
for /f "tokens=1*delims==" %%a in ('set "#"') do echo(%%b
set "flag=true"
)
) else echo !line!
) else echo(!line!
))>output.txt
this copies all hello lines over the hello-hai lines in file1, i want to know how to add the word hai to the search in first file
#echo off
setlocal EnableDelayedExpansion
rem Find lines with both strings in file2
set i=0
for /F "delims=" %%a in ('findstr "hello" file2 ^| findstr "hai"') do (
set /A i+=1
set "file2[!i!]=%%a"
)
rem Merge file1 with the found lines in file2
set i=0
(for /F "delims=" %%a in (file1) do (
set "line=%%a"
if "!line:hello=!" neq "!line!" (
if "!line:hai=!" neq "!line!" (
set /A i+=1
for %%i in (!i!) do echo !file2[%%i]!
) else (
echo !line!
)
) else (
echo !line!
)
)) > output.txt
EDIT: New version added
Previous solution achieve a line-by-line replacement that works even if the matching lines are not together in any file (file merge), but requires that the number of matching lines be the same in both files. The new simpler version below works in the way requested by the OP:
#echo off
setlocal EnableDelayedExpansion
(for /F "delims=" %%a in (file1) do (
set "line=%%a"
if "!line:hello=!" neq "!line!" (
if "!line:hai=!" neq "!line!" (
if not defined flag (
findstr "hello" file2 | findstr "hai"
set flag=true
)
) else (
echo !line!
)
) else (
echo !line!
)
)) > output.txt
Try this:
#echo off &setlocal
set "tf1=%temp%\~%random%1"
set "tf2=%temp%\~%random%2"
set "tf3=%temp%\~%random%3"
set "tf4=%temp%\~%random%4"
set "pt=hello"
set "pu=hai"
<file1 findstr /lin "%pt%">"%tf1%"
<"%tf1%" findstr /li "%pu%">"%tf2%"
<file2 findstr /li "%pt%">"%tf3%"
<"%tf3%" findstr /li "%pu%">"%tf4%"
for /f "usebackqdelims=:" %%i in ("%tf2%") do (
if not defined st set "st=%%i"
set "fi=%%i"
)
set /a st-=1
<file1 (
for /l %%i in (1,1,%st%) do (
set "line="
set/p "line="
setlocal enabledelayedexpansion
echo(!line!
endlocal
))>"%tf1%"
<file1>"%tf3%" more +%fi%
copy /a "%tf1%"+"%tf4%"+"%tf3%"=output.txt>nul
del "%temp%\~*"
type output.txt
output is:
line1
line2
hello-hai-5
hello-7-hai
6-hai-hello
hello
#ECHO OFF
SETLOCAL
SET searching=Y
(
FOR /f "delims=" %%i IN (file1.txt) DO (
ECHO %%i|FIND "hello"|FIND "hai" >NUL
IF ERRORLEVEL 1 (ECHO(%%i) ELSE (
IF DEFINED searching TYPE "file2.txt"|FIND "hello"|FIND "hai"
SET "searching="
)
)
)>output.txt
TYPE output.txt
GOTO :EOF
Here's a version without tempfiles. It simply reproduces lines from file1 that don't contain BOTH of the target strings. When BOTH are found in the same line, it outputs all of those lines in file2 that contain both strings. The searching flag is used to ensure that the file2 lines are only output once.
It won't reproduce blank lines or lines that begin ;. Could be made to do so if required.

Resources