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

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.

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

Cut off block based on certain strings in a file

I have a task to cut off the block starting from certain string in the middle of a file and then to save this upper part of the file into a new file.
;---- Some text A
aaaaaaa1111
……..
aaaaaaa2222
;-----Some text B
bbbbbbbbb1111
…………..
bbbbbbbbb2222
Now I am looking for a batch file to cut off the part starting from:
;-----Some text B
So after cut, the new file looks like:
;---- Some text A
aaaaaaa1111
……..
aaaaaaa2222
All the part starting from:
;-----Some text B
bbbbbbbbb1111
…………..
bbbbbbbbb2222
has been cut off.
I tried to use the Function from DOStip then call that function as below:
#ECHO OFF
REM.-- Prepare the Command Processor
SETLOCAL ENABLEEXTENSIONS
SETLOCAL ENABLEDELAYEDEXPANSION
echo.Extracting hello world block into "Load_SDK.M83" file
call:extractFromFile ";---- Some text A" ";---- Some text B">"Load_SDK.M83"
:extractFromFile - extract lines from a file between begin and end mark
:: - %~1: begin mark, use '...$' mark to allow variable substitution
:: - %~2: optional end mark, default is end of file
:: - %~3: optional source file, default is THIS file
SETLOCAL
set bmk=;---- Some text A
set emk=;---- Some text B
set src=C:\Files\Load_all.M83
set /a b=-1
set /a e=-1
if "%src%"=="" set src=%~f0& ::- if no source file then assume THIS file
for /f "tokens=1,* delims=:" %%a in ('"findstr /n /b /c:"%bmk%" "%~f0""') do (
set b=%%a
set bmk=%%b
)
if /i %b%==-1 echo.ERROR: begin mark '%bmk%' not found in '%src%'&GOTO:EOF
if "%emk%"=="" (set /a e=2000000000) ELSE (
for /f "delims=:" %%a in ('"findstr /n /b /c:"%emk%" "%~f0""') do (
if /i %b% LSS %%a if /i !e!==-1 set e=%%a& rem -- find only the first one after b
)
)
if /i %e%==-1 echo.ERROR: end mark '%emk%' missing in '%src%'&GOTO:EOF
if /i %b% GEQ %e% echo.ERROR: end mark '%emk%' detected before begin mark '%bmk%' in '%src%'&GOTO:EOF
for /f "delims=: tokens=1,*" %%a in ('"findstr /v /n /b /c:"#$*ReturnAll*$#" "%src%""') do (
if /i %b% LSS %%a if /i %%a LSS %e% (
if "%bmk:~-1%"=="$" (
rem --sustitution variables within %%b
call echo.%%b
) ELSE (
rem --no variable substitution
echo.%%b
)
)
)
GOTO:EOF
Based on my comment, a one line single For loop with an If and a GoTo seems to perform the task as shown in your question:
#(For /F UseBackQDelims^=^ EOL^= %%A In ("source.txt") Do #If /I Not "%%A"==";-----Some text B" (Set /P "=%%A"<Nul&Echo=) Else GoTo :EOF)>"result.txt"

Batch scripting: read lines and execute a command after every other line read

Suppose I have a text file like this
node1.log
node2.log
node3.log
node4.log etc...
I want to read each line by line and execute
alan.exe node1.log node2.log
alan.exe node3.log node4.log
etc..
What is the best way to accomplish this?
#echo off
setlocal EnableDelayedExpansion
for /F "delims=" %%a in (file.txt) do (
if not defined line (
set "line=%%a"
) else (
ECHO alan.exe !line! %%a
set "line="
)
)
Give this a try. File.txt will have your log file names.
#echo off
setlocal enabledelayedexpansion
FOR /F "delims=" %%G IN ('find /c /v "" ^<file.txt') DO SET NUM=%%G
SET /A NUM=NUM / 2
< file.txt (
FOR /L %%G IN (1,1,%NUM%) DO (
SET /P LINE1=
SET /P LINE2=
echo mypgm.exe !LINE1! !LINE2!
)
)
pause
Output
mypgm.exe node1.log node2.log
mypgm.exe node3.log node4.log
mypgm.exe node5.log node6.log
Press any key to continue . . .
Remove the word echo and replace mypgm.exe with the program you want to run. The echo is just in there for the proof of concept.
Like this:
#echo off
setlocal enabledelayedexpansion
set args=
set n=2
for /f "tokens=*" %%x in (file.txt) do (
set args=!args! %%x
set /a n -= 1
if !n! EQU 0 (
alan !args!
set args=
set n=2
)
)

how to encrypt a text file using batch?

How can i encrypt the content in a text file using batch? and how can i decrypt it?
i have tried setting each letter to a number but i do not know how to split the string into each letter and do that.
I watched a video on youtube that help turn letters into numbers but it did not do it with a file.
this is the code he provides in the video.
#echo off
setlocal enableDelayedExpansion
set /p code=Text:
set chars=0123456789abcdefghijklmnopqrstuvwxyz
for /L %%N in (10 1 36) do (
for /F %%C in ("!chars:~%%N,1!") do (
set "code=!code:%%C=%%N!"
)
)
echo !code!
pause
Please help Thank you
#ECHO OFF
SET abet=abcdefghijklmnopqrstuvwxyz!##-/\ .0123456789
SET cipher1=8p#j4 9z\6w.ae#0u2r5o!xk-cf1b3g7hmqil/sntdvy
(
FOR /f "delims=" %%a IN (q20794050.txt) DO (
SET line=%%a
CALL :encipher
)
)>q20794050.txt.1
(
FOR /f "delims=" %%a IN (q20794050.txt.1) DO (
SET line=%%a
CALL :decipher
)
)>q20794050.txt.2
GOTO :EOF
:decipher
SET morf=%abet%
SET from=%cipher1%
GOTO trans
:encipher
SET from=%abet%
SET morf=%cipher1%
:trans
SET "enil="
:transl
SET $1=%from%
SET $2=%morf%
:transc
IF /i "%line:~0,1%"=="%$1:~0,1%" SET enil=%enil%%$2:~0,1%&GOTO transnc
SET $1=%$1:~1%
SET $2=%$2:~1%
IF DEFINED $2 GOTO transc
:: No translation - keep
SET enil=%enil%%line:~0,1%
:transnc
SET line=%line:~1%
IF DEFINED line GOTO transl
ECHO %enil%
GOTO :eof
Here's a way to do it using a simple Cæsar (substitution) code.
abet can be set (possibly from a file) to the set of characters that you want to encode. Similarly, cipher1 can be set to the transled set - just make sure that each character in abet also appears in cipher1.
Any character that appears in the input text but not in abet will not be translated.
I used q20794050.txt:
The quick brown fox [jumps] {over} the lazy dog 9876543210.
9876543210 The quick brown fox !##-/\ jumps over the lazy dog.f
Which was encoded to q20794050.txt.1 :
5z4huo\#whp2#xeh #kh[6oa0r]h{#!42}h5z4h.8c-hj#9hyvdtns/liqm
yvdtns/liqh5z4huo\#whp2#xeh #khf1b3g7h6oa0rh#!42h5z4h.8c-hj#9m
(Note that there is a Space at the end of that last line...)
And was successfully disencrypted to q20794050.txt.2
Note: the above won't handle certain problem characters like %&|><
I've only used lower-case so any upper-case would be translated to lower-case by the process. If you remove the /i from the IF statement, then case will be preserved, but you'd have to add the upper-case letters to abet and cipher1 else the encrypted file will contain the upper-case characters verbatim.
Note that
(for...do (...))>somefilename
will create a new file somefilename containing any data ECHOed - even if the ECHO occurs in a subroutine.
#echo off
setlocal enableDelayedExpansion
for /f "tokens=* delims= " %%h in ('type %1') do (
set text=%%h
)
set chars=0123456789abcdefghijklmnopqrstuvwxyz
for /L %%N in (10 1 36) do (
for /F %%C in ("!chars:~%%N,1!") do (
set "text=!text:%%C=-%%N!"
)
)
echo !text! > %userprofile%\Desktop\encrypted.txt
pause
(using a different .bat file)
#echo off
setlocal enableDelayedExpansion
for /f "tokens=* delims= " %%h in ('type %1') do (
set text=%%h
)
set chars=0123456789abcdefghijklmnopqrstuvwxyz
for /L %%N in (10 1 36) do (
for /F %%C in ("!chars:~%%N,1!") do (
set "text=!text:%%N=%%C!"
)
)
for /f %%K in ("!text!") do (
set "text=!text:-=!"
)
echo !text! > %userprofile%\Desktop\decrypted.txt
pause

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