So I have a text file that I read which contains multiple lines of words. For now it contains "Successful" and failed.
Here's my code.
setlocal enabledelayedexpansion
for /l %%x in (1, 1, 50) do (
for /f "tokens=*" %%a in (D:\Errors.txt) do echo %%x %%a >>D:\list.txt
)
Basically what I want to output are the words in Errors.txt at random which is mapped from 1 - 50.
Currently this is the output of my code and it's not at random. Also the numbering repeats which I guess is expected due to the loop. Any help would greatly be appreciated. Thanks!
1 Successful
1 Failed
2 Successful
2 Failed
3 Successful
3 Failed
4 Successful
4 Failed
5 Successful
5 Failed
6 Successful
6 Failed
7 Successful
7 Failed
Basically end goal should be like this. Successful/Failed are applied at random while the numbers 1 - 50 are consistent.
1 Successful
2 Failed
3 Failed
4 Successful
5 Successful
6 Successful
7 Failed
This method works with any number of lines in the Errors.txt file:
#echo off
setlocal EnableDelayedExpansion
(
rem Load the lines from the file
set n=0
for /F "delims=" %%a in (D:\Errors.txt) do (
set "line[!n!]=%%a"
set /A n+=1
echo !n! %%a
)
rem Repeat same lines the rest of times in random order
set /A nP1=n+1
for /L %%i in (!nP1!,1,50) do (
set /A i=!random! %% n
call echo %%i %%line[!i!]%%
)
) > D:\list.txt
#echo off
setlocal EnableDelayedExpansion
set n=0
(
REM read from file
for /f "tokens=*" %%a in (D:\Errors.txt) do (
set /a n+=1
echo !n! %%a
)
REM for the rest until 50:
for /l %%a in (!n!,1,49) do (
set /a n+=1
set /a x=!random! %% 2
if !x!==0 (
echo !n! successful
) else (
echo !n! failed
)
)
)>D:\list.txt
type D:\list.txt
Related
There is a batch file that looks for Pen=n in the list.txt and changes its value (n) randomly from the given row of ten numbers (set "var[pen]=1 2 3 4 5 6 7 8 9 10"). But if there are more than ten numbers say twenty (set "var[pen]=1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20") or hundred, it is still picking a number from first ten ones ignoring the rest.
#echo off
setlocal EnableDelayedExpansion
set "file=D:\list.txt"
set "temp=D:\temp.txt"
set "var[pen]=1 2 3 4 5 6 7 8 9 10" &
for /L %%i in (1,10,1%time:~-2%) do set "rand=!random!"
(for /F "usebackq tokens=1,2 delims==" %%a in ("%file%") do (
if defined var[%%a] (
call :getRandomValue var="!var[%%a]!"
echo %%a=!var!
) else if "%%b" neq "" (
echo %%a=%%b
) else (
echo %%a
)
)) > "%temp%"
move /Y "%temp%" "%file%"
pause > nul && pause > nul
goto :EOF
:getRandomValue value="list"
set /A "rand=!random:~-1!+1"
for /F "tokens=%rand%" %%v in (%2) do set "%1=%%v"
Any help would be appreciated.
edit:
the list.txt contains a list of stuff like pen paper rubber etc. with the corresponding value next to it.
pen=5
pencil=43
paper=0
rubber=22
what the bat file does is just putting random number picking in up from the row of numbers provided. in the following case it would change the value of pen to a random number from 1 to 10. but if I add some extra numbers more than ten it will then just ignore them.
You forgot to specify the origin post of this problem. In such a post, there is not any specification about how the probabilities must be given, but all the 3 examples provided have 10 probable values, so I assumed that all probabilities have 10 values. The fix is add the number of probabilities each value can have:
#echo off
setlocal EnableDelayedExpansion
rem Define the probabilities for new values
set "value[apple]=0 0 0 0 0 0 0 1 1 1" & set "num[apple]=10" & rem 0 (70%) or 1 (30%)
set "value[peach]=0 0 0 0 0 1 2 3 4 5" & set "num[peach]=10" & rem from 0 (50%) to 5 (the rest 50%)
set "value[banana]=54 68 82 96" & set "num[banana]=4" & rem each 25%
rem Randomize
for /L %%i in (1,10,1%time:~-2%) do set "ran=!random!"
(for /F "tokens=1,2 delims==" %%a in (input.ini) do (
if defined value[%%a] (
call :getRandomValue value=%%a
echo %%a=!value!
) else if "%%b" neq "" (
echo %%a=%%b
) else (
echo %%a
)
)) > output.ini
move /Y output.ini input.ini
goto :EOF
:getRandomValue value=item
set /A "ran=%random%%%num[%2]+1"
for /F "tokens=%ran%" %%v in ("!value[%2]!") do set "%1=%%v"
exit /B
You also forget (again) to provide the real format of the input file, that include [headers]:
[Berries]
Strawberry=1
Blackberry=-13
Blueberry=100
Cherry=6
[Fruits]
apple=0
peach=4
banana=18
orange=-2.5
[Vegetables]
Potato=44
Tomato=2
Onion=0
Garlic=17
EDIT 2022/01/08: New method added as requested in comment
As I already said, you have not specified the rules to define the probable values. I proposed a method that works correctly based on your first example, but then you define values that does not conform with my proposed method (10 possible values, like in your first example). I modified the method and then you invented values that does not conform either: "Why 100 values?" "Because any number above 31 will make the method fail..."
I modified the method (again) so you can define the probabilities via value:percent pairs. Here it is:
#echo off
setlocal EnableDelayedExpansion
rem Define the probabilities for new values as value:percent pairs
set "value[apple]=23:17 68:83" & rem 23 at 17%, 68 at 83%
set "value[peach]=0:50 1:10 2:10 3:10 4:10 5:10" & rem from 0 (50%) to 5 (the rest 50%)
set "value[banana]=54:25 68:25 82:25 96:25" & rem each 25%
rem Randomize
for /L %%i in (1,10,1%time:~-2%) do set "ran=!random!"
(for /F "tokens=1,2 delims==" %%a in (input.ini) do (
if defined value[%%a] (
call :getRandomValue %%a
echo %%a=!value!
) else if "%%b" neq "" (
echo %%a=%%b
) else (
echo %%a
)
)) > output.ini
move /Y output.ini input.ini
goto :EOF
:getRandomValue item
set /A "ran=%random%%%100+1, val=0"
for %%a in (!value[%1]!) do for /F "tokens=1,2 delims=:" %%x in ("%%a") do (
if %ran% gtr !val! set "value=%%x"
set /A val+=%%y
)
exit /B
What you are aiming to do is to randomly index from a list, which requires you to first determine the number of items in the list.
one method of doing so:
#Echo off
Set "var[pen]=a b c d e f g h i"
Rem enable enviroment for !expanison!
Setlocal EnableDelayedExpansion
Rem Build 'array', splitting string on spaces and incrementing array size count
Set _i=1& Set "item[1]=%var[pen]: =" & Set /A "_i+=1" & Set "item[!_i!]=%"
Rem index randomly from known array size [one indexed]
For /f delims^= %%i in ('Set /A !random! %%!_i! + 1')Do Echo(Item:%%i = !Item[%%i]!
Pause
I am attempting to figure out a way to do returning if then statements in the for command, here's the code so far:
We have a file called: File.cfg with multiple numbers (no more than 6 numbers):
1
3
4
6
2
5
Setting those numbers as variables:
setlocal enabledelayed expansion
setlocal
set /a count=1
for /F "usebackq delims=" %%a in ( File.cfg ) do (
set line!count!=%%a
set /a count+=1
)
Then attempting to do a returning if then operations:
set /a count=0
echo 1 > list.txt
:Loop
set /a count+=1
echo %count% > list.txt
FOR /F "usebackq delims= " %%a in (list.txt) do (
echo !line%%a!
if %%a==7 goto :eof
if !line%%a!==1 goto 1
if !line%%a!==2 goto 2
if !line%%a!==3 goto 3
if !line%%a!==4 goto 4
if !line%%a!==5 goto 5
if !line%%a!==6 goto 6
)
Example of the goto #'s
:1
code
code
code
goto loop
Though in the end, the batch program ends prematurely, mainly at count 1.
Final output results:
( echo !line1!
if 1 == 7 goto :eof
if !line1! == 1 goto 1
if !line1! == 2 goto 2
if !line1! == 3 goto 3
if !line1! == 4 goto 4
if !line1! == 5 goto 5
if !line1! == 6 goto 6
)
1
Not sure why you have the complicated code unless you are trying to do a proof of concept on something. In my experience the easiest way to achieve your desired outcome is to do this.
#echo off
for /F "usebackq delims=" %%a in ("File.cfg") do CALL :%%a
REM END OF MAIN Functions below
GOTO :EOF
:1
ECHO IN 1
GOTO :EOF
:2
ECHO IN 2
GOTO :EOF
REM Shortened for brevity
The code above will output
IN 1
IN 3
IN 4
IN 6
IN 2
IN 5
If you really want to use array variables then again the easiest solution is the following code.
#echo off
setlocal enabledelayedexpansion
set "count=0"
for /F "usebackq delims=" %%a in ("File.cfg") do (
set /a "count+=1"
set "line!count!=%%a"
)
FOR /L %%G IN (1,1,%count%) DO CALL :!line%%G!
REM END OF MAIN Functions below
GOTO :EOF
:1
ECHO IN 1
GOTO :EOF
:2
ECHO IN 2
GOTO :EOF
REM Shortened for brevity
The aforementioned code will also output
IN 1
IN 3
IN 4
IN 6
IN 2
IN 5
This question already has an answer here:
Split a CSV file into multiple files with header and given number of records
(1 answer)
Closed 1 year ago.
I have a text file. The first line is header. rest of the lines are data. It may contain thousand lines of data. I need to write a batch script which will split the master files into many files each of them contains maximum 500 lines of data and the same header as master file.
Master file
heder
1
2
3
4
.
.
.
.
1501
it will split the file into 4 files. The fourth one will have the header and 1501
You can get a total count of lines in a file using find and calculate the number of files needed by using a for /l loop on the count of the lines in steps of 500
the below approach examples such - in this way files are created with the header and lines output in accordance with the 500 per file using a paired GTR LEQ conditional test.
#Echo off & CD /D "%~dp0"
:# Primary environment has Delayed Expansion Disabled until after assignment of input
:# to retain '!' characters.
Setlocal EnableExtensions DisableDelayedExpansion
Set "line[i]="
Set "files="
:# Get a count of total lines and how many files to make per 500
for /f %%a in ('type "infile.txt"^|find "" /v /c') do Set /A TTL=%%a-1
For /l %%i in (0 500 %TTL%)Do Set /A files+=1
Set /P "Header=" <"infile.txt"
:# Delayed expansion provides protection against poison characters
Setlocal EnableDelayedExpansion
:# Create or Overide each outfile using the assigned input from set /p
For /l %%i in (1 1 %files%)Do >"Outfile%%i.txt" Echo(!Header!
Endlocal
:# Outer for /f loop skips header line; counts each line in.
:# Inner for /l loop iterates over group size with assigned offset 'Stop'
:# Dual GTR LEQ conditional test of Lne[i] used to output in desired group
For /f "Skip=1 Delims=" %%G in (infile.txt)Do (
Set /A "Line[i]+=1"
Set "Line=%%G"
Setlocal EnableDelayedExpansion
Set "file[i]=0"
For /l %%i in (0 500 !TTL!)Do (
Set /A "Stop=%%i+500"
Set /A "file[i]+=1"
If !Line[i]! GTR %%i If !Line[i]! LEQ !Stop! (
Title File: !file[i]! / !files! Line: !Line[i]! / !TTL!
>>"Outfile!file[i]!.txt" Echo(!Line!
)
)
Endlocal
)
Here you go:
#echo off
setlocal EnableDelayedExpansion
set /a maxNoOfLinesPerFile = 500
set /a lineCount = 0
set /a fileCount = 0
set header=""
set outFileNamePrefix=outFile
for /F "tokens=*" %%A in (source.txt) do (
if !lineCount!==0 (
set header=%%A
) else (
set /a n = !lineCount! %% !maxNoOfLinesPerFile!
REM echo !n!
if !n!==1 (
set /a fileCount = fileCount + 1
set outFileName=!outFileNamePrefix!_!fileCount!.txt
echo !outFileName!
echo !header! >> !outFileName!
echo %%A >> !outFileName!
) else (
echo %%A >> !outFileName!
)
)
set /a lineCount = lineCount + 1
)
I have a batch file that accepts store numbers and sets them to an array and then iterates through the array. When I double click my batch file it gives the error:
256 was unexpected at this time.
But when I run it from the console/command prompt it runs fine.
Here is my code.
#echo off
setlocal enabledelayedexpansion
set index=0
:getstore
set /a index=index + 1
set /P store[%index%]=Enter SLC store number:
:ask
set /P answer=Do you want to enter another store number (Y/N):
if /i "%answer%" == "n" (
set length=%index%
goto next
)
if /i "%answer%" == "y" (
goto getstore
) else goto ask
:next
for /L %%i in (1,1,%length%) do (
if %store% LSS 256 (
for /L %%k in (1,1,5) do ping 192.168.!store[%%i]!.%%k -n 1 |find "TTL"
)
if %store% GTR 255 (
set /a store=%store% - 255
for /L %%k in (1,1,5) do ping 10.0.!store[%%i]!.%%k -n 1 |find "TTL"
)
)
When you double click a batch file, a new cmd instance will be executed, one instance where store has not been initialized, so the line
if %store% LSS 256 (
fails as %store% is empty.
Thanks MC ND!
Your comment got me thinking.
When I was calling store in the if statement I needed to use the !! and also the index.
This is my edited (now working) code:
:next
for /L %%i in (1,1,%length%) do (
for /f "tokens=* delims=0" %%j in ("%store[%%i]%") do set store[%%i]=%%j
if !store[%%i]! LSS 256 (
for /L %%k in (1,1,5) do ping 192.168.!store[%%i]!.%%k -n 1 |find "TTL"
)
if !store[%%i]! GTR 255 (
set /a store=%store% - 255
for /L %%k in (1,1,5) do ping 10.0.!store[%%i]!.%%k -n 1 |find "TTL"
)
)
I am using Microsoft Windows XP [Version 5.1.2600]
Trying to do this.
Trying to create the variable dynamically and then read the value out of that variable in a loop.
#ECHO off
SET SQL1=TEST
SET SQL2=TEST1
SET SQL3=TEST2
SET SQL=SQL
SETLOCAL ENABLEDELAYEDEXPANSION
SET /A number=0
FOR /l %%A IN (1,1,3) DO (
SET /A number = number + 1
echo !number!
echo %SQL%!number!
)
endlocal
Output should be
1
test
2
test2
3
test3
I am getting
C:\temp>c.bat
1
SQL1
2
SQL2
3
SQL3
Please help!
Ugh.
First way (note that instead of your number variable, it uses the loop counter variable %%A):
#ECHO off
SET SQL1=TEST
SET SQL2=TEST1
SET SQL3=TEST2
SETLOCAL ENABLEDELAYEDEXPANSION
SET /A number=0
FOR /l %%A IN (1,1,3) DO (
SET /A number = number + 1
echo !number!
echo !SQL%%A!
)
endlocal
Second way (ugly but it does what you want):
#ECHO off
SET SQL1=TEST
SET SQL2=TEST1
SET SQL3=TEST2
SETLOCAL ENABLEDELAYEDEXPANSION
SET /A number=0
FOR /l %%A IN (1,1,3) DO (
SET /A number = number + 1
echo !number!
for %%i in (!number!) do (echo !SQL%%i!)
)
endlocal