I have this code:
#echo off
setlocal EnableDelayedExpansion
rem FILL ARRAY
set n=0
for %%a in (A B C) do (
set fname[!n!]=%%a
set /A n+=1
)
rem FIRST OUTPUT
for /L %%i in (0,1,2) do (
echo !fname[%%i]!
)
echo/
rem SECOND OUTPUT
echo !fname[0]!
echo !fname[1]!
echo !fname[2]!
echo/
rem THIRD OUTPUT DOESN'T WORK
set n=0
for %%a in (A B C) do (
echo !fname[!n!]!
set /A n+=1
)
And get:
A
B
C
A
B
C
n
n
n
For some reasons I need output in third style and expect the same output like in first and second case but I can't understand what's wrong with it.
Update.
Thank you, folks. I guess I've confused you a little but really I need to use this output in variable, so I've found this working solution, maybe it'll help somebody else:
rem THIRD OUTPUT WORKS
set n=0
for %%a in (A B C) do (
for /f "tokens=2* delims==" %%x in ('set fname[!n!]') do (
<... using %%x...>
)
set /A n+=1
)
rem %%x contains output now and can be used anywhere
You need another layer of parsing.
call echo %%fname[!n!]%%
or
for %%n in (!n!) do echo !fname[%%n]!
cures your third case.
Incorporated into your script:
#echo off
setlocal EnableDelayedExpansion
rem FILL ARRAY
set n=0
for %%a in (A B C) do (
set fname[!n!]=%%a
set /A n+=1
)
rem skip first and second output
rem THIRD OUTPUT WORKS
set n=0
for %%a in (D E F) do (
call echo Copy "%%a" "%%fname[!n!]%%"
for %%n in (!n!) do ECHO cOpy "%%a" "!fname[%%n]!"
for /f "tokens=1* delims==" %%x in ('set fname[!n!]') do echo coPy "%%a" "%%y"
set /A n+=1
)
of course use just one of the three lines (and don't forget to remove the ECHO after troubleshooting)
Related
I need to make batch file that takes two arguments.
First is txt file containing matrix A containing integer values delimited by ','.
Second argument is also txt file. It containts array B of integers delimited by ' '.
Batch file should create file named result.txt which contains matrix C, where
C[i][j]=A[i][j]+k[i][j] where k[i][j] is number of occurrence number A[i][j] in array B. I would be very thankful if anyone could help me. I tried to solve this but for command in dos is killing me...
For example:
matrix.txt
1,2,3
4,5,6
array.txt
1 3 2 5 1
results.txt
3 3 4
4 6 6
This problem is interesting! This is how I would solve it:
rem Count the number of times each number appear in array B
for each line in %2 do (
for each number %%n in line do (
add 1 to times[%%n]
)
)
rem Process the matrix A
for each line in %1 do (
rem Initialize output line
set "out="
for each number %%n in line do (
set termC = %%n + times[%%n]
join termC to out
)
echo out
)
EDIT: As user aschipfl indicated, this answer is just the pseudo-code of how to solve this problem that I posted as a hint for you (because post complete solutions when the OP had not showed his/her own efforts to solve the problem is not a good practice here).
However, now that another working solution had been posted, I completed previous pseudo-code into a fully working program:
#echo off
setlocal EnableDelayedExpansion
rem Check the arguments
if "%~2" equ "" echo Usage: %~NX0 MatrixA.txt ArrayB.txt & goto :EOF
if not exist "%~1" echo MatrixA file not found & goto :EOF
if not exist "%~2" echo ArrayB file not found & goto :EOF
rem Count the number of times each number appear in array B
for /F "usebackq delims=" %%b in ("%~2") do (
for %%n in (%%b) do (
set /A "times[%%n]+=1"
)
)
rem Process the matrix A and create matrix C
(for /F "usebackq delims=" %%a in ("%~1") do (
set "out="
for %%n in (%%a) do (
set /A termC=%%n + times[%%n]
set "out=!out! !termC!"
)
echo !out:~1!
)) > result.txt
#echo off
setlocal enabledelayedexpansion
for /f "usebackq delims=" %%a in ("path+array.txt") do (
set "array_all=%%a"
)
set array_n=0
call :sub_2 %array_all%
set array_n_all=%array_n%
for /f "usebackq delims=" %%a in ("path+matrix.txt") do (
set "current_line=%%a"
set "current_line=!current_line:,= !"
set "matrix_new="
call :sub_1 !current_line!
echo !matrix_new:~1!>>"path+results.txt"
)
exit /b
:sub_1
set "current_value=%1"
if not defined current_value exit /b
set "array_rest=!array_all:%current_value%=!"
set array_n=0
call :sub_2 %array_rest%
set /a current_value_new=%current_value%+%array_n_all%-%array_n%
set "matrix_new=%matrix_new% %current_value_new%"
shift
goto sub_1
:sub_2
set "array_tmp=%1"
if not defined array_tmp exit /b
set /a array_n+=1
shift
goto sub_2
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
)
)
I am working on a batch file. I have an array:
setlocal enabledelayedexpansion
set Base_list[0]=Base1
set Base_list[1]=Base2
set Base_list[2]=Base3
set Base_list[3]=Base4
set Base_list[4]=Base5
set Base_list[5]=Base6
set Current_Node=Node1
if "%Current_Node%" == "Node1" ( for /l %%a in (0 ,%counter% , %Base_list%) do (
// do some stuff
)
)
How do I print this array named Base_list?
How can I iterate through this array?
You have a couple minor errors in your code:
You have not initialized the counter variable.
The format of FOR command is slightly different
A comment is inserted via REM command, not //
This is the right version of your code:
#echo off
setlocal enabledelayedexpansion
set Base_list[0]=Base1
set Base_list[1]=Base2
set Base_list[2]=Base3
set Base_list[3]=Base4
set Base_list[4]=Base5
set Base_list[5]=Base6
set Current_Node=Node1
rem Explicitly set the counter:
set counter=5
if "%Current_Node%" == "Node1" (
for /l %%a in (0 , 1, %counter%) do (
rem do some stuff
echo Element %%a in Base_list array is: !Base_list[%%a]!
)
)
However, this code may be written in a simpler way:
#echo off
setlocal enabledelayedexpansion
rem Create the array via elements placed in a FOR command
rem at same time, generate the counter:
set counter=0
for %%a in (Base1 Base2 Base3 Base4 Base5 Base6) do (
set Base_list[!counter!]=%%a
set /A counter+=1
)
rem Adjust the counter because the array is zero-based:
set /A counter-=1
set Current_Node=Node1
if "%Current_Node%" == "Node1" (
for /l %%a in (0 , 1, %counter%) do (
rem do some stuff
echo Element %%a in Base_list array is: !Base_list[%%a]!
)
)
I suggest you to read this post on array management in Batch files.
Print:
set base_list[
(This assumes you don't want to keep numeric sequence if the index >9 and there are no unwanted variables with names starting base_list[ - you don't specify)
Iterate:
for /f "tokens=1*delims==" %%a in ('set base_list[ 2^>nul') do echo %%b
or
for /f "tokens=1*delims==" %%a in ('set base_list[ 2^>nul') do echo %%a has value %%b
depending on quite what you want to do - same conditions as "print".
I think, you are completely confused by for /L.
The correct Syntax is for /L %%i in (<start>,<step>,<end>) do...
#echo off
setlocal enabledelayedexpansion
set Base_list[0]=Base1
set Base_list[1]=Base2
set Base_list[2]=Base3
set Base_list[3]=Base4
set Base_list[4]=Base5
set Base_list[5]=Base6
set Current_Node=Node1
REM list array:
set base_list[
REM list values only:
for /f "tokens=2 delims==" %%i in ('set Base_list[') do echo %%i
REM get size of the array:
for /f %%i in ('set base_list[ ^|find /c "="') do set count=%%i
echo size is %count%
REM subtract one because array starts with 0:
set /a count-=1
if "%Current_Node%" == "Node1" for /l %%a in (0,1,%count%) do (
echo %%a: some stuff with !base_list[%%a]!
)
I'm splitting the file every 6000 lines with the script below but I'm having a problem with it....
Every line of my txt file has the character '=' so when the batch is treating the file, where I have the '=' the line stops and goes to the next one (I don't have the end of each line, anything that follows the = is deleted).
FOR %%X IN (*.TXT) do (
setlocal ENABLEDELAYEDEXPANSION
SET BFN=%%X
SET LPF=6000
SET SFN=%%X_6000_
)
REM ==============================
SET SFX=%BFN:~-3%
SET /A LineNum=0
SET /A FileNum=1
For /F "delims==" %%l in (%BFN%) Do (
SET /A LineNum+=1
echo %%l >> %SFN%!FileNum!.%SFX%
if !LineNum! EQU !LPF! (
SET /A LineNum=0
SET /A FileNum+=1
)
)
endlocal
Can Someone help me out?
Sample of file:
A88A0A1891BAA9=B088A00000003800001==00000038000
A88A0A1B13A0BB=B088A00000089000002==00000890000
A88A0A1A13B830=B088A000000B3800003==00000B38000
A88A0A00331831=B088A00000010A00004==0000010A000
A88A0A10B31B39=B088A00000090A00005==0000090A000
A88A0A19A3AA89=B088A00000089800006==00000898000
A88A0A19AA0318=B088A000000A0100007==00000A01000
A88A0A08911913=B088A00000008800008==00000088000
A88A0A1089A139=B088A00000098300009==00000983000
A88A0A1BB8BBA8=B088A000000AA100010==00000AA1000
A88A0A0A8B9199=B088A00000098100011==00000981000
A88A0A19AA8A9B=B088A00000088900012==00000889000
A88A0A0B380A13=B088A00000099A00013==0000099A000
A88A0A13899A18=B088A00000088A00014==0000088A000
A88A0A1A188910=B088A0000008A800015==000008A8000
A88A0A10930AA0=B088A0000009B900016==000009B9000
A88A0A09338A88=B088A000000A0A00017==00000A0A000
A88A0A11A98930=B088A000000AAB00018==00000AAB000
Setting the LPF (lines Per File) to 6, here is the result (first of 3 files):
A88A0A1891BAA9
A88A0A1B13A0BB
A88A0A1A13B830
A88A0A00331831
A88A0A10B31B39
A88A0A19A3AA89
Thanks!
Remove the second = in the delims :
For /F "delims=" %%l in (%BFN%) Do (
delims== means the command tries to split each line with =
What you need is
For /F "tokens=*" %%l in (%BFN%) Do
This means "give me the whole line without splitting it into tokens"
Also in your code above the nesting of the do ( ) blocks seems wrong.
It looks like the first for loop simply sets environment variables and does nothing else. Did you actually run this code?
It should be
#echo off
FOR %%X IN (*.TXT) do (
setlocal ENABLEDELAYEDEXPANSION
SET BFN=%%X
SET LPF=6000
SET SFN=%%X_6000_
REM ==============================
SET SFX=%BFN:~-3%
SET /A LineNum=0
SET /A FileNum=1
For /F "tokens=*" %%l in (%BFN%) Do
SET /A LineNum+=1
echo %%l >> %SFN%!FileNum!.%SFX%
if !LineNum! EQU !LPF! (
SET /A LineNum=0
SET /A FileNum+=1
)
)
endlocal
)
Good Afternoon!
Long time reader, first time poster! I have been having a lovely time trying to modify a working batch file to account for variability. The situation is that I have a variable-size text document that normally would be able to be split into sections of 252 lines. The code below worked like a champ:
#echo off & setlocal EnableDelayedExpansion
set param=%*
if not defined param (
echo.
echo. Usage: batchsplit [device:][pathname]filename
goto :EOF
)
set param=%param:"=%
if not exist "%param%" (
echo.
echo. File "%param%" not found
goto :EOF
)
for %%j in ("%param%") do (
set name=%%~dpnj
set ext=%%~xj
)
for /F %%j in ('type "%param%" ^| find /V /C ""') do set Full=%%j
set /A Split=%Full%/252
for /L %%G in (1,1,%Split%) do type nul > "%name%_%%G%.new"
set X=1
set N=1
set Q=1
set limit = 252
for /F "tokens=1* delims=]" %%j in ('type "%param%" ^| find /V /N ""') do (
set /A N+=1
set /A Q+=1
echo.%%k>> "%name%_!X!%.new"
if !Q! gtr 252 (
set /A X+=1
set /A Q=1
) else if !N! gtr Full (goto theend
)
)
:theend
echo split into %split% files with 252 lines each
rem pause
However, there were some changes to the formatting of the text, and now instead of four pages of 63 lines per split file, it can be completely variable. The only constant is this final line, which precedes the remaining space for a 63 line page:
ON THIS FORM IS COMPLETE AND CORRECT AS NOTED:___________________
Note that there is a single space in front of it, as well as multiple spaces, a colon, and underscore characters. Being the meathead that I am, I thought I could insert an if-then statement into the for loop to trigger the batch to split to the next page. However, I could be further from that right now. This is the code I have been smashing my head with:
rem #echo off & setlocal EnableDelayedExpansion
setlocal EnableDelayedExpansion
set param=%*
if not defined param (
echo.
echo. Usage: textsplit [device:][pathname]filename
goto :EOF
)
set param=%param:"=%
if not exist "%param%" (
echo.
echo. File "%param%" not found
goto :EOF
)
for %%j in ("%param%") do (
set Name=%%~dpnj
set ext=%%~xj
)
for /F %%j in ('type "%param%" ^| find /V /C ""') do set Full=%%j
set stopvar= ON THIS FORM IS COMPLETE AND CORRECT AS NOTED:___________________
set Split=1
echo %stopvar%
set X=1
type nul > "%name%_!X!%.new"
set N=1
set Q=1
set S=0
set L=63
for /F "tokens=1* delims=]" %%j in ('type "%param%" ^| find /V /N ""') do (
set /A N+=1
echo %N%
set /A Q+=1
echo %Q%
echo.%%k>> "%name%_!X!%.new"
if ["%%k%" == "!stopvar!"] (
set /A S+=1
)
if !Q! gtr !L! (
if !S! == 1 (
set /A X+=1
set /A Q=1
type nul > "%name%_!X!%.new"
set /A Split+=1
set S=0
)
else set /A L+=63
else if !N! gtr Full goto theend
)
:theend
echo Split into %split% files!
pause
The premise is that every 63 lines, the stop variable (S) is checked. If it is off (0) then the batch will continue to write for another 63 lines (one page). If the stopvar matches the line that is being read by the for loop, S becomes 1. When the program checks again, it will create a new file and begin writing to that new file. Right now, based on turning off #echo off the hangup is at the for loop. See below:
C:\Users\theangryasiancp\Desktop\TEXT_Split_Test>rrtextsplit texttest.txt
C:\Users\theangryasiancp\Desktop\TEXT_Split_Test>rem #echo off & setlocal Enabl
eDelayedExpansion
C:\Users\theangryasiancp\Desktop\TEXT_Split_Test>setlocal EnableDelayedExpansio
n
C:\Users\theangryasiancp\Desktop\TEXT_Split_Test>set param=texttest.txt
C:\Users\theangryasiancp\Desktop\TEXT_Split_Test>if not defined param (
echo.
echo. Usage: rrtextsplit [device:][pathname]filename
goto :EOF
)
C:\Users\theangryasiancp\Desktop\TEXT_Split_Test>set param=texttest.txt
C:\Users\theangryasiancp\Desktop\TEXT_Split_Test>if not exist "texttest.txt" (
echo.
echo. File "texttest.txt" not found
goto :EOF
)
C:\Users\theangryasiancp\Desktop\TEXT_Split_Test>for %j in ("texttest.txt") do
(
set Name=%~dpnj
set ext=%~xj
)
C:\Users\theangryasiancp\Desktop\TEXT_Split_Test>(
set Name=C:\Users\theangryasiancp\Desktop\TEXT_Split_Test\texttest
set ext=.txt
)
C:\Users\theangryasiancp\Desktop\TEXT_Split_Test>for /F %j in ('type "texttest.
txt" | find /V /C ""') do set Full=%j
C:\Users\theangryasiancp\Desktop\TEXT_Split_Test>set Full=567
C:\Users\theangryasiancp\Desktop\TEXT_Split_Test>set stopvar= ON THIS FORM IS C
OMPLETE AND CORRECT AS NOTED:___________________
C:\Users\theangryasiancp\Desktop\TEXT_Split_Test>set Split=1
C:\Users\theangryasiancp\Desktop\TEXT_Split_Test>echo ON THIS FORM IS COMPLETE
AND CORRECT AS NOTED:___________________
ON THIS FORM IS COMPLETE AND CORRECT AS NOTED:___________________
C:\Users\theangryasiancp\Desktop\TEXT_Split_Test>set X=1
C:\Users\theangryasiancp\Desktop\TEXT_Split_Test>type nul 1>"C:\Users\theangry
asiancp\Desktop\RRRR_Split_Test\texttest_!X!.new"
C:\Users\theangryasiancp\Desktop\TEXT_Split_Test>set N=1
C:\Users\theangryasiancp\Desktop\TEXT_Split_Test>set Q=1
C:\Users\theangryasiancp\Desktop\TEXT_Split_Test>set S=0
C:\Users\theangryasiancp\Desktop\TEXT_Split_Test>set L=63
C:\Users\theangryasiancp\Desktop\TEXT_Split_Test>
What are your thoughts? Where am I going wrong with the batch? I wish I could use something different, but alas I cannot, for internal company reasons. Thanks for your help!
#ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
SET "name=q23396663"
SET "ext=.txt"
SET /a pagelength=10
SET "targetstring= ON THIS FORM IS COMPLETE AND CORRECT AS NOTED:___________________"
SET /a filenum=0
SET /a linecount=pagelength + 1
FOR /f "tokens=1*delims=]" %%a IN (
'find /v /n "" "%name%%ext%"') DO (
IF !linecount! GEQ %pagelength% (
SET /a linecount=0
SET /a filenum+=1
)
>>U:\%name%_!filenum!.new ECHO(%%b
IF "%%b"=="%targetstring%" SET /a linecount=pagelength
SET /a linecount+=1
)
GOTO :EOF
For testing purposes, I set up a file q23396663.txt containing your trigger data. I've left the destination directory as U:\ which suits me, and the pagelength at 10 which makes my testing easier.
#echo off
setlocal EnableDelayedExpansion
REM ------------------THIS SECTION SPECIFIES THE FILE-------------------------
set param=%*
if not defined param (
echo.
echo. Usage: filesplit [device:][pathname]filename
goto :EOF
)
set param=%param:"=%
if not exist "%param%" (
echo.
echo. File "%param%" not found
GOTO :EOF
)
for %%j in ("%param%") do (
set name=%%~dpnj
set ext=%%~xj
)
ECHO SPLITTING %name%.%ext% .................
REM ----------------THIS SECTION SETS THE VARIABLES---------------------------
set "trigger= ON THIS FORM IS COMPLETE AND CORRECT AS NOTED:___________________"
set /a pagelength=63
set /a filenum=0
set split=1
set /a linecount=pagelength
set stopvar=0
REM ------------------THIS SECTION IS THE FOR LOOP----------------------------
FOR /f "skip=2 tokens=1* delims=]" %%a IN (
'find /v /n "" "%name%%ext%"') DO (
SET /a linecount-=1
IF !linecount! LEQ 0 (
IF !stopvar! EQU 1 (
SET /a "linecount=pagelength"
SET /a filenum+=1
SET /a split+=1
SET /a stopvar-=1
) else set /a "linecount=pagelength"
)
echo.%%b>> "%name%_!filenum!.new"
IF "%%b"=="%trigger%" (
set /a "stopvar+=1"
REM THIS TRIGGERS TO CHANGE OUTPUT
set /a linecount+=1
REM THIS WILL ADJUST THE OUTPUT EOF
)
)
REM ----------------THIS SECTION ENDS THE FOR LOOP----------------------------
ECHO Split into %split% files!
ping 1.1.1.1 -n 1 -w 2500 > nul
REM THIS PAUSES THE BATCH FOR A SEC
As I posted in the comment above, this is just a variation of the first answer that accounts for blank spaces if they are needed to keep the output files from having unnecessary whitespace on top. This is especially helpful when a print manager is just spitting out whitespace until the end of the page before starting the next part instead of going straight to the next portion.