copy lines from a text file to another - batch-file

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.

Related

Batch remove part of string after “-1” is found or any other number “-[0-9]”

I got a file containing a string on each line like this:
fruit-apple-1.5.6
vegtable-sla-mc5-6.5-16515
extra-huh-9.5-511-515
extra-3.2
I am iterating over it and want it to remove the part of the string on the right after in find "-" + any number "-0","-1","-2","-9",...
so output should be
fruit-apple
vegtable-sla-mc5
extra-huh
extra
this is code i have but it only works with a "-" i cant combine it so it takes "-" + any number like "-1","-5","-2",...
for /f "delims=|" %%A in ("!fileNameCheck:-=|!") do (
echo stripped string = %%A
)
complete code not necessary i think but in case u need it below
#echo off
SETLOCAL ENABLEDELAYEDEXPANSION
set "RawPath=%~dp0"
FOR /F "USEBACKQ TOKENS=*" %%M IN ("%RawPath%/mods") DO (
REM for %%f in (*.jar) do (
Set "fileNameCheck=%%M"
for /f "delims=|" %%A in ("!fileNameCheck:-=|!") do (
Echo [46m%%A[0m
if exist "%~dp0%%A*.jar" (
REM echo [32mFound %%A "%~dp0%%A*.jar"[0m
if exist "%~dp0%%M" (
REM echo [42mUp to Date[0m [32m%%A "%~dp0%%M"[0m
) else (
for %%j in (*.jar) do (
echo %%j |find "%%A" >nul
if not errorlevel 1 (
echo [41mDifferent Version[0m [31m%%j [0m[90mNewer version[0m [32m%%M[0m
)
)
)
) else (
REM echo [31mMissing %%A[0m
)
)
)
pause
Given that the strings do not contain any of the caracters ?, *, < and >, the following script should do the trick:
#echo off
setlocal EnableExtensions DisableDelayedExpansion
rem // Define constants here:
set "_ROOT=%~dp0."
set "_FILE=mods.txt"
rem // Read file line by line:
for /F usebackq^ delims^=^ eol^= %%L in ("%_FILE%") do (
rem // Store current line, initialise variables:
set "LINE=%%L" & set "PREV=-" & set "COLL=-"
setlocal EnableDelayedExpansion
rem /* Split line string at every `-` and iterate through items;
rem (`?`, `*`, `<`, `>` must not occur in the string!): */
for %%I in ("!LINE:-=" "!") do (
endlocal & set "ITEM=%%~I"
rem // Check whether item only consists of numerals and `.`:
(
rem // This loop executes when there are other characters:
for /F "delims=0123456789. eol=." %%J in ("%%~I") do (
setlocal EnableDelayedExpansion
rem /* Rebuilt string with currently found items; if there
rem are other items following numeric ones, keep them: */
for /F "delims=" %%K in ("!COLL!!PREV:~1!-!ITEM!") do (
endlocal & set "COLL=%%K" & set "PREV=-"
)
)
) || (
rem // This section runs when there are numerals and `.`:
setlocal EnableDelayedExpansion
for /F "delims=" %%K in ("!PREV!-!ITEM!") do (
rem /* Store numeric items in a separate buffer; if there
rem are no other items following, this is dismissed: */
endlocal & set "PREV=%%K"
)
)
setlocal EnableDelayedExpansion
)
rem // Return rebuilt line string:
echo(!COLL:~2!
endlocal
)
endlocal
exit /B
The example input file mods.txt:
fruit-apple-1.5.6
vegtable-sla-mc5-6.5
extra-huh-9.5
extra-3.2
test-9.15.5
keep-forge
name-subname-10.5-55.5
globalxp-1.16.5
mix-1.2-string-10.5-55.5-more
mix-1.2-string-10.5-55.5-more-3.4
mix-1.2-string-10.5-55.5-more-3.4-5.6-7
8.9
1.2.3-lead
1.2.3-4.5.6-7.8.9-lead-mult
leads to the following output:
fruit-apple
vegtable-sla-mc5
extra-huh
extra
test
keep-forge
name-subname
globalxp
mix-1.2-string-10.5-55.5-more
mix-1.2-string-10.5-55.5-more
mix-1.2-string-10.5-55.5-more
1.2.3-lead
1.2.3-4.5.6-7.8.9-lead-mult
One way is to replace the - with \ and then use variable substitution to strip the %%~ni part from the string. We just need to remove the first and last occurrence then from the string. findstr will determine that the end of string needs to be -num.*
#echo off
setlocal enabledelayedexpansion
for /f "delims=" %%A in ('dir /b /s *.jar ^| findstr /RC:"-[0-9].*$"') do (
set "line=%%~nxA"
for %%i in ("!line:-=\!") do set "final=%%~pi"
set "final=!final:~0,-1!-"
echo !final! | findstr /RC:"\\[0-9].*$" >nul 2>&1
if !errorlevel! equ 0 (
for %%s in ("!final!") do set "final=%%~ps"
set final=!final!
)
set "final=!final:~0,-1!"
set "final=!final:~1!"
echo !final:\=-!
)
the edited code should take care of the additional - as per your comment example name-subname-10.5-55.5
Here's an untested idea, which may not be particularly quick, especially if you have a large number of strings in your mods file:
#Echo Off
SetLocal EnableExtensions DisableDelayedExpansion
For /F %%G In ('Echo Prompt $E ^| %SystemRoot%\System32\cmd.exe /D'
) Do Set "$E=%%G"
For /F Delims^=^ EOL^=^ UseBackQ %%G In ("%~dp0mods") Do (Set "Line=%%G"
SetLocal EnableDelayedExpansion
For /L %%H In (0 1 9) Do For /F Delims^=^ EOL^= %%I In (
'(Echo(^) ^| Set /P "=!Line:-%%H="^&:"!" 0^<NUL') Do Set "Line=%%I"
Echo(%$E%[46m!Line!%$E%[0m
EndLocal
)
Pause

Batch Split each line into multiples lines

My txt file looks like:
A1;A2;A3
B1;B2
I want to split it like:
A1;;;A2
A2;;;A3
A3;;;A3
B1;;;B2
B2;;;B2
The rule is: For each line take two adjacent elements and create a new output line with them, for the last element of a line: create also a new output line, but use the element twice.
Here is my try:
(
for /f "tokens=1-4 delims=;" %%a in (%FilePath%) do (
for /f "tokens=1-4 delims=;" %%x in (%FilePath%) do (
echo %%a;;;%%y
)
)
)>%FilePath_Final%
But it gives the wrong format:
A1;;;A2
A1;;;B2
B1;;;A2
B1;;;B2
How can I use batch commands to split the lines so that the expected result is obtained?
PS: A1, A2, B1 etc. are just some string examples, I can have various strings
Here is an example of a file content:
XB8998901;XB8998900;8051191;24048271;24048270
XB0134812;XB0134810;XB0134801;XB0134800
XB6312701;XB6312700
XB6314201;XB6314200
The ouput should look like:
XB8998901;;;XB8998900
XB8998900;;;8051191
8051191;;;24048271
24048271;;;24048270
24048270;;;24048270
XB0134812;;;XB0134810
XB0134810;;;XB0134801
XB0134801;;;XB0134800
XB0134800;;;XB0134800
XB6312701;;;XB6312700
XB6312700;;;XB6312700
XB6314201;;;XB6314200
XB6314200;;;XB6314200
#echo off
setlocal enabledelayedexpansion
set "last="
(for /f "delims=" %%a in (old.txt) do (
for %%b in (%%a) do (
if defined last echo !last!;;;%%b
set "last=%%b"
)
echo !last!;;;!last!
set "last="
))>new.txt
fc new.txt compare.txt
old.txt (your example file):
XB8998901;XB8998900;8051191;24048271;24048270
XB0134812;XB0134810;XB0134801;XB0134800
XB6312701;XB6312700
XB6314201;XB6314200
compare.txt (desired output from your example):
XB8998901;;;XB8998900
XB8998900;;;8051191
8051191;;;24048271
24048271;;;24048270
24048270;;;24048270
XB0134812;;;XB0134810
XB0134810;;;XB0134801
XB0134801;;;XB0134800
XB0134800;;;XB0134800
XB6312701;;;XB6312700
XB6312700;;;XB6312700
XB6314201;;;XB6314200
XB6314200;;;XB6314200
Output:
Vergleichen der Dateien new.txt und compare.txt
FC: Keine Unterschiede gefunden
(Translation: Comparing files new.txt and compare.txt; FC: no differences encountered)
Use this:
#echo off
Setlocal enabledelayedexpansion
for /f "tokens=1,2,3 delims=;" %%a in ('type pathoffile ^| find "A"') do (set 1=%%a & set 2=%%b & set 3=%%c)
for /f "tokens=1,2 delims=;" %%a in ('type pathoffile ^| find "B"') do (set 4=%%a & set 5=%%b)
set n=1
:loop
set /a m=n+1
if "!%n%:~0,1!"=="!%m%:~0,1!" (
echo !%n%!;;;!%m%! >>filepath_final
) else (
echo!%n%!;;; >>filepath_final
)
set /a n=n+1
if %m% equ 5 goto :eof
goto loop

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
)
)

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.

how to join 2 lines using batch file

I have a text file that have unknown number of lines , some lines begins with patterns , I want to join the lines that begins with patterns with the next line , so for example
name=jimmy
age=19 id=23423 site=www.xxx.com
bla bla
name=katy
age=15 id=234543 site=www.yyy.com
name=ross
age=29 id=54564 site=www.ZZZZ.com
the output should be
name=jimmy age=19 id=23423 site=www.xxx.com
bla bla bla
name=katy age=15 id=234543 site=www.yyy.com
name=ross age=29 id=54564 site=www.ZZZZ.com
so the pattern is 'name' and it should join next line
I thougt to use sed but I dont know how
help please
Well, here's a straightforward script:
#echo off
setlocal enabledelayedexpansion
set "INPUT_FILE=input.txt"
set "OUTPUT_FILE=output.txt"
set prev=
for /f "tokens=*" %%f in (%INPUT_FILE%) do (
for /f "tokens=1,2 delims==" %%g in ("%%f") do (
if "!prev!" neq "" (
echo !prev! %%f >>%OUTPUT_FILE%
set prev=
) else (
if "%%g" equ "name" (
set prev=%%f
) else (
echo %%f >>%OUTPUT_FILE%
set prev=
)
)
)
)
#echo off
setlocal EnableDelayedExpansion
set pattern=name
set patternLen=4
call :ProcessFile < input.txt > output.txt
goto :EOF
:ProcessFile
set line=
set /P line=
if not defined line exit /B
if "!line:~0,%patternLen%!" equ "%pattern%" (
set /P nextLine=
set "line=!line! !nextLine!"
)
echo !line!
goto ProcessFile
Previous Batch file have the problem that it ends at the first empty line in the input file. However, this problem may be fixed if needed.

Resources