Converting decimal 100 to 31 30 30 in Batch - batch-file

I'm trying to convert a number from a text file - lets say number.txt - from decimal 100 to ASCII 31 30 30.
Is there something I can do in batch?
I tried several things I've found on SO already - but never had the right output.
Later after I have converted that - I need to add one number up after some execution. So lets say after 109 / 31 30 39 - it should be 110 31 31 30 and not 31 30 3a for example.
Can you give me a hint?
setlocal enabledelayedexpansion
for /f "tokens=*" %%a in (nummer.txt) do (
set line=%%a
set a=!line:~0,1!
set line=%%a
set b=!line:~1,1!
set line=%%a
set c=!line:~2,1!
set /a mitte=3!a!3!b!3!c!
echo 0F0900000A00143030303030303030303030303030303030!mitte!00>com3

Please see if the following `Rem`arked batch-file example helps you out.
#Echo Off
SetLocal EnableDelayedExpansion
Rem Undefine any existing variable named inputNum.
Set "inputNum="
Rem Read input number from first line of input file.
Set /P "inputNum="<"nummer.txt"
Rem Exit script if inputNum was not defined.
If Not Defined inputNum GoTo :EOF
Rem Define a number of additional iterations [number results required - 1].
Set "#=9"
Rem Define an increment size.
Set "i=5"
Rem Define a variable for total increase, [# x i].
Set /A $=#*i
Rem Undefine an existing variable named arg.
Set "arg="
Rem Begin looping for stated iterations.
For /L %%G In (0,%i%,%$%)Do (
Set /A arg=inputNum+%%G
Rem Call subfunction passing the input number as an argument.
Call :Sub "!arg!"
Rem If successful,
If Defined mitte (
Rem Output resultant number sequence.
Echo !mitte!
) Else (
Rem Exit if no result sequence.
GoTo EndIt
)
)
:EndIt
Rem Allow time to read output before ending.
Pause
EndLocal
GoTo :EOF
:Sub
Rem Undefine any existing variable named mitte.
Set "mitte="
Rem Split each character of passed argument.
For /F Delims^=^ EOL^= %%G In ('"Cmd /U/C Echo(%~1|Find /V """')Do (
Rem prefix each digit of inputNum with 3.
If Not Defined mitte (Set "mitte=3%%G")Else Set "mitte=!mitte!3%%G")
Rem return to next command line after previous Call
Exit /B
For testing, you should only need to ensure that your input file path is correct, (line 6). I have additionally include a facility to output a specific number of additional iterations, (line 10), with a fixed increment, (line 12). Please adjust those as necessary.
What that does if nummer.txt contains only 401, with 9 additional iterations incrementing by 5 should output:
343031
343036
343131
343136
343231
343236
343331
343336
343431
343436
After testing, you'll probably want to replace Echo !mitte! with (Echo 0F0900000A00143030303030303030303030303030303030!mitte!00)>COM3, (line 26)

Related

Musical chairs with line texts in batch

I still cannot find a solution to my problem.
What I desire: I have a txt file that contains 16 lines. Those lines begin with . and this is the only thing they have in common. To start with, all the content from line 16 is replaced by the content of line 15 and all line 15 is replaced by line 14 and so forth, until line 2 is replaced by line 1.
Note: the word LINE and numbers are just for reference. In fact, lines can have any alphanumeric character and also some special as - : | *. Lines can also be empty (only having the .)
#echo off
setlocal enabledelayedexpansion
set y=c:\FILES\TEST.txt
set /a count=17
:A
set /a count-=1
The first 'count' should be 16
for /f "delims=. tokens=%count%*" %%r in (%y%) do set L0=%%t
tokens=16 or searches the whole txt for the 16th . character
set L%count%=%L0:~1,133%
variable L16 receives LINE16
echo !L%count%! -^> This must be line %count%
LINE16 -> This must be line 16
if !count!==1 (goto B) else (goto A)
As 16 is not 1, the next 'count' will GOTO A and receive 15
:B
set /a e=17
set /a d=16
:N
set /a e-=1
set /a d-=1
The first 'e' equals to 16 and 'd' equals to 15
call jrepl "!L%e%!" "!L%d%!" /F %y% /M /O -
The first 'count' would replace "!L16!" to "!L15!"
echo !L%e%! -^> This must be line %e%
LINE16 -> This must be line 16
if !e!==2 (goto EOF) else (goto N)
As 16 is not 1, the next 'e' will GOTO N and receive 15
:EOF
echo END
exit/b
Another viewpoint that gives the same output is:
I'll start by saying that I'm astounded that you've got a program/process which writes to the first line of an existing file, overwriting the existing content/without a carriage return.
This solution is similar to Stephans existing answer, but all within one step:
#Echo Off
SetLocal EnableExtensions
Set "y=C:\FILES\TEST.txt"
Rem Create backup.
Copy /Y "%y%" "backup.tmp" 1> NUL 2>&1 || Exit /B
Rem Single step task.
( Echo(
For /F "Tokens=1,* Delims=:" %%G In (
'%__AppDir__%findstr.exe /BLN "." "backup.tmp"^
^| %__AppDir__%findstr.exe /BR "[123456789]: 1[012345]:"'
) Do Echo %%H
) 1> "%y%"
Rem Optionally delete backup.
Rem Del "backup.tmp"
The last line is Remarked, it is a copy of your before file, do not unremark it for actual deletion until you're sure that the resultant test.txt content is what you wanted.

merge multiple text files, removing all headers and the new header will be changed as follows:

Assuming we have this text files
*0000000000003000345800091600000000000002082019 0
*000000000000322322930002160000000DOU JIJEL 1
*000000000000306156240007000000000TIC TAHER 1
The header contains always what follows :
From position 1 to position 21 we have always this:
*00000000000030003458 which is an «unchangeable» value. It contains 21 characters.
From position 22 to 34, we got 13 characters which represent the sum of the amounts contained in every line the text file from position 22 to 34.
To clarify ; if you look at the header you’ll see from position 22 to 34 :
0009160000000 which is 91 600 000,00
It’s an amount of money, which is the sum of the amounts in the first and second line.
First line : 0002160000000 which is 21 600 000,00
Second line : 0007000000000 which is 70 000 000,00
21 600 000,00+70 000 000,00=91 600 000,00
« If we have in the first line 3162160000000 it means the amount in 31 621 600 000,00
If we have in the first line 0000000541000 it means the amount is 5 410,00 »
From position 35 to 41, we have seven characters, which represent the number of amounts contained in the text file.
We have From position 35 to 41 0000002, and we have two lines except the header, so the sum is 2.
If for example we have 714 lines, the position 35 to 41 in the header will be 0000714, and so on.
So, if I have two text files, and I want to merge them together in one file, in a way that we’ll have:
Only one header and All the lines in the text files.
The lines of course will be unchanged.
But the header will be changed as I explained above, in addition to that and from position 42 to position 62, will always be of the values or the characters contained in the header of the text files I want to merge, which are always the same.
That means that the header will be changed only from position 22 to position 41.
I've managed to remove the headers, but the new header I write it manually
#echo off
setlocal enabledelayedexpansion
if exist output.txt del output.txt
set "var="
for /r %%i in (*.txt) do (
if "%%~nxi" NEQ "output.txt" (
set "var="
for /f "usebackq skip=1 delims=" %%b in ("%%~i") do (
set var=%%b
if "!var!" NEQ "" Echo !var!
))) >> output.txt
this code will remove the header of the text files
So I expect the new header to be calculated automatically
The 32-bits integer values that set /A command can manage only allows to correctly add two numbers up to 9 (decimal) digits, but is very simple to overpass this limitation: just split a large number in two (or more) parts and add them separately. Be aware that when the result of any part exceeds its number of digits, such "overflow digit" (called Carry) must be passed (in the units position) to the next part.
#echo off
setlocal EnableDelayedExpansion
rem Initialize variables to manage first line
rem 01234567890123456789012345678901234567890123456789012345678901
rem /---unchangeable----\/amnt7\/amC6\/lins7\/----unchangeable---\
rem *0000000000003000345800091600000000000002082019 0
set /A amount7=10000000, amountC6=10000000, lines7=10000000
rem Process all files. Group all output to same file
(for /R %%i in (*.txt) do (
rem Input from each file
< "%%i" (
rem Read the first line and accumulate it
set /P header=
set /A amountC6+=10!header:~28,6!
set /A amount7+=1!header:~21,7!+!amountC6:~1,1!, amountC6=10!amountC6:~2!, lines7+=1!header:~34,7!
rem Copy the rest of lines
findstr "^"
)
rem Send all "rest of lines" to temporary file
)) > output.tmp
rem Add result header to temporary file, and delete it
(
echo %header:~0,21%%amount7:~1%%amountC6:~2%%lines7:~1%%header:~41%
type output.tmp
) > output.txt
del output.tmp
#ECHO OFF
setlocal enabledelayedexpansion
if exist output.txt del output.txt
set "headerproduced="
set "header="
set "var="
:pass2
for /r %%i in (*.txt) do (
if "%%~nxi" NEQ "output.txt" (
set "var="
if defined headerproduced (
if !headerproduced!==0 set /a headerproduced=1&echo !header!
for /f "usebackq skip=1 delims=" %%b in ("%%~i") do (
set "var=%%b"
if "!var!" NEQ "" Echo !var!
)
) else (
rem header not yet produced
for /f "usebackq delims=" %%b in ("%%~i") do if not defined var (
if defined header (
rem subsequent headers - accumulate
set "var=%%b"
set /a var1=1!header:~34,7! + 1!var:~34,7!
set /a var2=1!header:~28,6! + 1!var:~28,6!
set /a var3=1!header:~21,7! + 1!var:~21,7!
if !var2! geq 3000000 set /a var3+=1
set "header=!header:~0,21!!var3:~-7!!var2:~-6!!var1:~-7!!header:~41!"
) else (
rem very first header
set "header=%%b"
set "var=1"
)
)
)
)
) >> output.txt
if not defined headerproduced set /a headerproduced=0&goto pass2
GOTO :EOF
The syntax SET "var=value" (where value may be empty) is used to ensure that any stray trailing spaces are NOT included in the value assigned. In your posted code, there appears to be trailing spaces on lines - especially the set var=%%b which would generate 4 extra spaces at the end of each dataline.
This code works by using header to contain the new header for the file.
At first, no header has yet been encountered. When a file is read, var is set to nothing and each line of the file is processed.
When the first file is read, if defined header is FALSE so the header line is recorded in header and var set to some value so that it is defined. Subsequent lines of the file are ignored courtesy of the if not defined var gate.
On reading the remaining files, header is now defined, so we need to accumulate data. The accumulated data is assigned back to header in the appropriate spots. We then need to deal with adding the two fields. This is where we encounter batch's quirky maths.
Batch uses 32-bit signed-integers for its maths operations. That's fine for the shorter number, but the longer needs to be split into two - I chose the leading 7 digits and the trailing 6 digits.
Next minor matter is that batch regards a numeric string starting 0 as Octal, so we simply poke a 1 in front of each, add them up and use the last 6 or 7 digits of the result. In the case of the 6-digit portion, we can have an overflow - 1999998 + 1000003 = 3000001 - 3000000 or greater means we have overflow and need to increment the 7-digit portion.
Once all of the files have been read, header contains the required value but no header has yet been generated. We return to pass2 having set headerproduced to a significant value.
On the second pass, headerproduced now has a value. If that value is 0, we echo out the headerline and alter headerproduced to prevent multiple accumulated-headerlines being produced.
After that, output each line bar the first of each file as before.

need to read from line a to line b in a batch file

#echo off
cls
Color 0A
:Read
setlocal EnableDelayedExpansion
set file=WinSCP-5.11.2-ReadMe.txt
call :ReadInLines
call :EchoLines
echo insert other code here
pause
endlocal
(goto) 2>nul
:ReadInLines
set Counter=0
for /f "DELIMS=" %%i in ('type %file%') do (
set /a Counter+=1
title Lines In File: !Counter!
set "Line_!Counter!=%%i"
)
(goto) 2>nul
:EchoLines
For /L %%C in (1,1,%Counter%) Do (echo %%C. !Line_%%C!)
pause
So this is my code at the moment
It is able to successfully read and output the file as whole but I want to work on a way that doesn't require scrolling (for bigger files)
basically what i need to be able to do is read a certain amount of lines
example:
read lines 1 to 8 but also read lines 5 to 13
basically i need to be able to interchange the numbers it reads to, a label to call is preferred
finished code:
call.bat:
#echo off
cls
Color 0A
:: double call
call text-read-lines-alt.bat 1 8
call text-read-lines-alt.bat 9 20
pause
:: multiselect (a) (b) (a) (b) etc...
call text-read-lines-alt.bat 1 20 23 29
pause
:: call then calling outside text range (outputs first but not second)
call text-read-lines-alt.bat 1 8
call text-read-lines-alt.bat 80 100
pause
:: another call outside text range (outputs nothing)
call text-read-lines-alt.bat 90 100
pause
text-read-lines-alt.bat:
#echo off
setlocal EnableDelayedExpansion
set file=WinSCP-5.11.2-ReadMe.txt
SET "parms=%*"
call :ReadInLines
call :EchoLines
echo insert other code here
endlocal
(goto) 2>nul
:ReadInLines
set Counter=0
for /f "DELIMS=" %%i in ('type %file%') do (
set /a Counter+=1
title Lines In File: !Counter!
CALL :gate !counter!
IF DEFINED RECORD set "Line_!Counter!=%%i"
)
(goto) 2>nul
:EchoLines
For /L %%C in (1,1,%Counter%) Do IF DEFINED line_%%C (echo %%C. !Line_%%C!)
GOTO :EOF
:gate
SET "record="
IF NOT DEFINED parms GOTO :EOF
FOR /f "tokens=1,2*" %%x IN ("%parms%") DO (
IF %1 gtr %%y SET "parms=%%z"&GOTO gate
IF %1 geq %%x SET "record=Y"
)
GOTO :EOF
and here is what all the hard work went to: http://old-school-gamer.tk/batch/text-reader/releases/
:D
#ECHO OFF
setlocal EnableDelayedExpansion
set file=WinSCP-5.11.2-ReadMe.txt
set file=100lines.txt
SET "parms=%*"
call :ReadInLines
call :EchoLines
echo insert other code here
pause
endlocal
(goto) 2>nul
:ReadInLines
set Counter=0
for /f "DELIMS=" %%i in ('type %file%') do (
set /a Counter+=1
title Lines In File: !Counter!
CALL :gate !counter!
IF DEFINED RECORD set "Line_!Counter!=%%i"
)
(goto) 2>nul
:EchoLines
For /L %%C in (1,1,%Counter%) Do IF DEFINED line_%%C (echo %%C. !Line_%%C!)
SET /a count=0
For /L %%C in (1,1,%Counter%) Do IF DEFINED line_%%C (
SET /a count +=1
echo !count!. !Line_%%C!
)
GOTO :EOF
:gate
SET "record="
IF NOT DEFINED parms GOTO :EOF
FOR /f "tokens=1,2*" %%x IN ("%parms%") DO (
IF %1 gtr %%y SET "parms=%%z"&GOTO gate
IF %1 geq %%x SET "record=Y"
)
GOTO :EOF
I started by recording parms=the command-tail. My 100lines.txt file is simply a file containing 100 lines "line 1".."line100"
CALLing the :gate procedure sets or clears record to specify whether the line in counter should be recorded or not. if defined works on the current status of the target variable - defined or not.
The :gate routine examines the parms string, assigning %%x to the first token, %%y to the second and %%z to the remainder of the parameters provided. If the current line number in %1 (from the calling loop) is greater then the second parameter, then assign parms to the rest of the string (which removes thefirst two parameters) and try again. parms will eventually become empty, so simply don't try processing it.
If the second parameter is not greater than the current line, see whether the current line is greater than or equal to the first parameter. If so, set record to a value so it becomes defined and hence the calling loop will record it.
So - say params is 10 13 21 28. %%x will be set to 10, %%y to 13 and %%z to 21 28. Until line 9, the line number will not be geq 10, so record remains clear. For lines 10 to 13, record will be set and the line recorded, on line 14, 14 is greater than 13, so parms becomes 21 28 and we try again.
I've modified the output procedure too. the if defined gate will only execute the echo if line_%%C is defined, so there'll be no empty lines. The downside is that the report will show the line number from the file.
The second procedure uses a fairly obvious method to serialise the output to produce the line numbers.
For example,
If the datafile contains
Line 1
Line 2
Line 3
Line 4
Line 5
Line 6
Line 7
Line 8
then if the parameters supplied are 3 5 meaning "lines 3 to 5 inclusive" then the output from
For /L %%C in (1,1,%Counter%) Do IF DEFINED line_%%C (echo %%C. !Line_%%C!)
will be
Line 3
Line 4
Line 5
(note each line has its original line number.
and the output from
SET /a count=0
For /L %%C in (1,1,%Counter%) Do IF DEFINED line_%%C (
SET /a count +=1
echo !count!. !Line_%%C!
)
will be
Line 3
Line 4
Line 5
(simply the same data but with the line numbers modified)
if you leave both of these output mechanisms in place, the output will be
Line 3
Line 4
Line 5
Line 3
Line 4
Line 5
that is, the first output concatenated with the second.
Hope msr.exe can help you for such file text processing.
msr -p file-paths -L begin-line -N end-line with -PAC to hide path/info/color.
But cannot read 2 ranges(read lines 1 to 8 but also read lines 5 to 13) at one time:
msr -p test.txt -L 1 -N 8 + msr -p text.txt -L 5 -N 13
See following screenshot.
msr.exe/msr.gcc* is a single exe tool about 1.5MB no dependencies for file/pipe text processing on Windows and Linux in my open project. See docs like peformance comparision with grep and findstr and built-in usage doc by running exe etc.

Update running unsigned long long sum in bat file

Is there a simple way to sum two numbers potentially >= 2*31 in a .BAT file?
I have a running sum, and argument %1 that is the name of an existing file.
set sum=4123456789
set fsize=%~z1
I'd like to add fsize to sum. Unfortunately fsize (and sum) can be as tiny as zero or 10's of gigabytes (%~z1 accurately reports >= 2*31 file sizes).
I know a program could do it, and I'll go that route if necessary, but I'd prefer to do it with a few added lines of .BAT logic.
I think the easiest way is to split the summands into two parts – integer and fractional Gigas (multiples of 1000000000), add the respective parts individually, then recombine them. See the following example script, which contains a lot of explanatory remarks:
#echo off
setlocal EnableExtensions DisableDelayedExpansion
rem // Initialise variables:
set /A "GIGASUM=0, FRACSUM=0"
:LOOP
rem // Get command line argument:
shift
set "NUM=%~0"
if not defined NUM goto :NEXT
rem // Check number for validity:
(for /F "delims=0123456789" %%N in ("%NUM%") do rem/) && (
echo ERROR: non-numeric characters encountered!
exit /B 1
)
rem // Split number into two parts, integer and fractional Gigas:
set "NUM=000000000%NUM%"
set "GIGA=%NUM:~,-9%" & set "FRAC=%NUM:~-9%"
rem // Remove leading zeros from integer Gigas:
for /F "tokens=* delims=0" %%N in ("%GIGA%") do set "GIGA=%%N"
rem // Sum up fractional Gigas and determine carry:
set /A "FRACSUM+=(1%FRAC%-1000000000)"
set "CARRY=%FRACSUM:~,-9%" & set "FRACSUM=000000000%FRACSUM%"
set "FRACSUM=%FRACSUM:~-9%"
rem // Sum up integer Gigas and regard carry:
set /A "GIGASUM+=GIGA+CARRY"
rem // Loop back to next summand:
goto :LOOP
:NEXT
rem // Remove leading zeros:
for /F "tokens=* delims=0" %%N in ("%GIGASUM%%FRACSUM%") do set "SUM=%%N"
if not defined SUM set "SUM=0"
rem // Return resulting sum:
echo %SUM%
endlocal
exit /B
The greatest possible sum amounts to 231 * 109 – 1 = 2147483647999999999, an overflow is not detected.
The required logic is not so complicated. Here it is one version:
#echo off
setlocal
:loop
set /p "pair=Enter two numbers separated by plus sign: "
if errorlevel 1 goto :EOF
for /F "tokens=1,2 delims=+" %%a in ("%pair%") do set "num1=%%a" & set "num2=%%b"
set "sum="
set "carry=0"
:nextDigit
set /A sum1=%num1:~-1%+%num2:~-1%+carry
set "sum=%sum1:~-1%%sum%"
set /A carry=sum1/10
set "num1=%num1:~0,-1%"
if not defined num1 set "num1=0"
set "num2=%num2:~0,-1%"
if not defined num2 set "num2=0"
if "%carry%%num1%%num2%" neq "000" goto nextDigit
echo The sum is: %sum%
goto loop

Echo Outputs When Writing to File

When I use this code to select a character from my list, it works just fine but when I write it to a file using:
echo %pwd%>>pwd.gen
It will some times put the word "ECHO" randomly in the middle of the strings generated. Here is an example:
jUrkunjcxC
ecRECHOsI5w0T
DmJfat13fT
UWXOysW7Gb
pPmS7138Ve
nFkh32ECHOJd1
You can see it appears in line 2 and 6. This only happens about 20% of the time.
Here is the code:
#echo off
title Password Generator
color f0
:firstRun
set /a cnt=0
cls
setlocal ENABLEEXTENSIONS ENABLEDELAYEDEXPANSION
set /p Len=What length should the password be?
set /a Len=%Len%-1
cls
set /p Amt=How many would you like to generate?
cls
goto start
:start
set alfanum=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
set pwd=
FOR /L %%b IN (0, 1, %Len%) DO (
SET /A rnd_num=!RANDOM! * 62 / 32768 + 1
for /F %%c in ('echo %%alfanum:~!rnd_num!^,1%%') do set pwd=!pwd!%%c
)
echo %pwd%>> pwd.gen
set /a cnt=%cnt%+1
if %cnt%==%Amt% goto end
goto start
:end
cls
echo Done!
echo Results have been saved to "pwd.gen"
echo.
choice /c YN /m "Restart?"
if %errorlevel%==1 goto firstRun
:start
set alfanum=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
set pwd=
FOR /L %%b IN (0, 1, %Len%) DO (
SET /A rnd_num=!RANDOM! * 62 / 32768 + 1
for /F %%c in ('echo %%alfanum:~!rnd_num!^,1%%') do set pwd=!pwd!%%c
)
alfanum is 26+26+10 = 62 characters long.
RANDOM gives a random number from 0-32,767
When RANDOM is above 32240, rnd_num gets set to 62
string indexing starts at 0 not 1
the for /F %%c command indexes alfanum:~62,1~ which is an empty string
it calls echo with no parameter, which prints ECHO is on. instead of returning a single character
for /F defaults to splitting strings with a space delimiter, which separates out the first word
%%c becomes ECHO
you add ECHO into the password.
This is a combination of a couple of things. While I'm not totally clear about the inner workings of the whole thing, I know what's causing it and how to fix it.
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 is 62 characters long. However, substrings in batch start with 0, so valid numbers go from 0 to 61. For whatever reason, an index-out-of-range combined with the ^ in 'echo %%alfanum:~!rnd_num!^,1%%' is causing the word ECHO to be displayed.
To get around this, simply don't add 1 when calculating rnd_num.
SET /A rnd_num=!RANDOM! * 62 / 32768

Resources