Batch file CSV string to pyramid - batch-file

I am working on one of the batch file and I have a specific requirement where I have a string "text1,text2,text3,text4...etc" & I would like to have my output as a pyramid like
text1
text1,text2
text1,text2,text3
text1,text2,text3,text4
..etc
My brain says that it is easily achievable, but not getting the logic! How could I do it through batch scripting (for loop)?

The method below allows you to have a list of comma-separated values that may contain spaces or Batch special characters. Of course, it also works with your simple values.
#echo off
setlocal EnableDelayedExpansion
set "string=text one,text <two>,text |three|,text &four&"
set "line="
for %%a in ("%string:,=","%") do (
set "line=!line!%%~a,"
echo !line:~0,-1!
)
Output:
text one
text one,text <two>
text one,text <two>,text |three|
text one,text <two>,text |three|,text &four&

#echo off
setlocal enableextensions enabledelayedexpansion
set "text=text1,text2,text3,text4,text5,text6,text7,text8"
set "output="
for %%a in (%text%) do (
if defined output ( set "output=!output!,%%a" ) else set "output=%%a"
echo(!output!
)
As the values are separated with commas, and commas are a default delimiter in for command, just iterate over the list concatenating the values as they are processed

You can make use of a variable in which on every loop, you'd append a text on it. You'll also need activate delayedexpansion so your variables get updated quick. for /l %%a in (;;) creates an infinite loop.
#echo off
setlocal enabledelayedexpansion
set var=text1
for /l %%a in (;;) do (
echo !var!
set var=!var!,text1
)
Edit: Noticed that your numbers actually increment. You can do:
#echo off
setlocal enabledelayedexpansion
set var=text1
for /l %%a in (2,1,100) do (
echo !var!
set var=!var!,text%%a
)
2 = initial value of %%a
1 = increment per loop
100 = maximum number but only with respect to condition. max number printed is 100 - 1 or 99.

Related

Batch - Replace a String in a Loop

i´ve Problems replacing a string in a loop
For example: I have a File called someBlabla.txt which has multiple lines with random sentences. Now i want to read the file line by line in a for loop and replace a specific char of a word by another. I want to use the shown string replace method, means %myVar:to_replace=replace%
Has someone any hints?
Here is my Script:
REM REPLACE EXAMPLE
#echo off
SETLOCAL ENABLEDELAYEDEXPANSION
:MAIN
set file=someBlaBla.txt
set "charToReplace=a"
set "replacer=Z"
for /f "tokens=*" %%a in (%file%) do (
set "replaced_line=%a:%charToReplace%=%replacer%%"
echo replacedLine=!replaced_line!
)
exit /b 0
Here is my textfile:
This is a sentence with an a
this is something
there is a car
and so on and so on
some a a a

Avoid a null value in last for loop iteration?

I have a text file with one string per line (only a couple lines total). This file needs to be searched and each string stored. The script will ultimately prompt the user to choose one of the stored strings (if more than one string/line is present in the file), but the for loop is iterating an extra time when I don't want it to.
I'm using a counter to check the number of iterations, and I also read that it's probably a NL CR regex issue, but the finstr /v /r /c:"^$" in the for file-set like in this post Batch file for loop appears to be running one extra time/iteration doesn't work for me (but I probably don't understand it correctly).
The "pref" term is because the strings are to be eventually used as a prefix of files in the same folder...
#echo off
setlocal enabledelayedexpansion
set /a x=1
for /f %%a in (sys.txt) do (
set pref!x!=%%a && echo %^%pref!X!%^% && set /a x+=1
)
echo last value of x = !x!
for /L %%a in (1,1,!x!) do (
echo !pref%%a!
)
REM The rest would be to prompt user to choose one (if multiple) and
REM then use choice as a prefix with a ren %%a %prefX%%%a
If the "sys.txt" contains three lines with strings A, B, C respectively, then the output I currently get is:
pref1
pref2
pref3
last value of x = 4
A
B
C
ECHO is off.
ECHO is off. is not desired, clearly.
You just need to change your increment structure like this. (set it before each line starting from a base of 0)
#Echo Off
Setlocal EnableDelayedExpansion
Set "i=0"
For /F "UseBackQ Delims=" %%A In ("sys.txt") Do (
Set/A "i+=1"
Set "pref!i!=%%A"
Echo(pref!i!)
Echo(last value of i = %i%
For /L %%A in (1,1,%i%) Do Echo(!pref%%A!

Trying to reformat a very large csv with a batch file

I have an application that exports data in the format:
1a,1b,1c1,1c2,1c3, ... (up to 1c100),1d1,1d2,1d3, ... (up to 1d100)
2a,2b,2c1,2c2,2c3, ... (up to 2c100),2d1,2d2,2d3, ... (up to 2d100)
etc.
and I am trying to reformat this into
1a,1b,1c1,1d1
1a,1b,1c2,1d2
.
.
1a,1b,1c100,1d100
2a,2b,2c1,2d1
2a,2b,2c2,2d2
etc.
I figured that if this can be done a row at a time I can just loop through the file. However I can't find a way of doing a single row with either tokens, a list, or even as a string function. There is too much data to process in a single operation (each value is about 12 chars). Tokens limit at (roughly) 64/202, a list at about 107/202 and a string at about 1000/2300
Does anyone know how this can be written into a new file?
I was trying things like:
#echo off
setlocal enableDelayedExpansion
set dimCnt=0
<example.csv (
set /p "dimList=" >nul
for %%D in (!dimList!) do (
set /a dimCnt+=1
set "dim[!dimCnt!]=%%D"
)
)
echo
for /l %%I in (3 1 102) do echo !dim[1]!,!dim[2]!,!dim[%%I]!
</code>
..besides the fact that I have missed out the last variable in the line (need to add 100 to it), I can't get more than about 80-110 values out of the list (I guess it depends on value string length)
#echo off
setlocal enableextensions enabledelayedexpansion
(for /f "tokens=1,2,* delims=," %%a in (example.csv) do (
set "data=%%c"
set "i=0"
for %%f in ("!data:,=" "!") do (
set /a "i+=1"
set "d[!i!]=%%~f"
)
set /a "end=!i!/2"
set /a "j=!end!+1"
for /l %%i in (1 1 !end!) do (
for %%j in (!j!) do echo %%a,%%b,!d[%%i]!,!d[%%j]!
set /a "j+=1"
)
)) > output.csv
endlocal
This iterates over the file, getting the first two tokens in the line (%%a and %%b), the rest of the line (%%c) is splitted and each value stored in an environment variable array (kind of). Then, the array is iterated from the start and from the middle, reading the needed values to append to %%a and %%b and generating output file.
#ECHO OFF
SETLOCAL
(
FOR /f "tokens=1,2,*delims=," %%a IN (u:\long.csv) DO (
SET rpta=%%a
SET rptb=%%b
CALL :rptcd %%c
)
)>newfile.txt
GOTO :EOF
:rptcd
SET /a lines=100
SET lined=%*
FOR /l %%x IN (1,1,99) DO CALL SET lined=%%lined:*,=%%
:loop
IF %lines%==0 GOTO :EOF
SET /a lines-=1
CALL SET lined=%lined:*,=%
FOR /f "delims=," %%x IN ("%lined%") DO ECHO %rpta%,%rptb%,%1,%%x&shift&GOTO loop
GOTO :eof
This should get you going - just need to change the input filename and output filename...
Your code does not work because SET /P cannot read more than 1023 bytes. At that point it returns the data read so far, and the next SET /P picks up where it left off. Adapting your code to compensate will be very difficult. You would be better off using FOR /F as in MC ND's answer. But beware, batch has a hard limit of 8191 characters per line in pretty much all contexts.
Better yet, you could use another scripting language like JScript, VBS, or PowerShell. Performance will be much better, and the code much more robust and far less arcane. I love working with batch, but it simply is not a good text processing language.

Batch file for loop unable to assign values from external file

So, I've got this basic text file called prev_batch.cfg that I want a batch script to read. prev_batch.cfg is a single line of text, but tokens are delimited with a comma. It looks something like:
apples,oranges,bananas,grapes,strawberries
I'd like each of those tokens to go into a specific variable I have setup in a for loop. The problem is only the first variable gets set within the loop. Nothing else. I want all the variables to be set to the tokens found within the delimited list in the .cfg file.
Here is what my batch script looks like up until the close of the FOR loop:
#ECHO ON
setlocal EnableDelayedExpansion
SET JOB=%1
SET USER=%2
SET ASSETROOT=%3
:: Read all the arguments for this batch script from external text file
FOR /F "delims=," %%a IN (%ASSETROOT%\users\%USER%\%JOB%\prev_batch.cfg) do (
SET JOB=%%a
SET USER=%%b
SET TEMPLATE=%%c
SET ASSETROOT=%%d
SET SHAREADDR=%%e
SET SHARENAME=%%f
SET SHAREDRIVE=%%g
SET SHAREUSER=%%h
SET SHAREPASS=%%i
)
I'm running the batch file and passing three command line parameters into it. I'm outputting the echo of the batch when it runs to a log file. And this is what I'm seeing:
C:\Windows\system32>setlocal EnableDelayedExpansion
C:\Windows\system32>SET JOB=99D0FAA9-22B8-4FE7-9321-21F5587E8177
C:\Windows\system32>SET USER=10
C:\Windows\system32>SET ASSETROOT=C:\app
C:\Windows\system32>FOR /F "delims=," %a IN (C:\app\users\10\99D0FAA9-22B8-4FE7-9321-21F5587E8177\prev_batch.cfg) do (
SET JOB=%a
SET USER=%b
SET TEMPLATE=%c
SET ASSETROOT=%d
SET SHAREADDR=%e
SET SHARENAME=%f
SET SHAREDRIVE=%g
SET SHAREUSER=%h
SET SHAREPASS=%i
)
C:\Windows\system32>(
SET JOB=99D0FAA9-22B8-4FE7-9321-21F5587E8177
SET USER=%b
SET TEMPLATE=%c
SET ASSETROOT=%d
SET SHAREADDR=%e
SET SHARENAME=%f
SET SHAREDRIVE=%g
SET SHAREUSER=%h
SET SHAREPASS=%i
)
try this:
FOR /F "usebackq tokens=1-9 delims=," %%a IN ("%ASSETROOT%\users\%USER%\%JOB%\prev_batch.cfg") do (
SET JOB=%%a
SET USER=%%b
SET TEMPLATE=%%c
SET ASSETROOT=%%d
SET SHAREADDR=%%e
SET SHARENAME=%%f
SET SHAREDRIVE=%%g
SET SHAREUSER=%%h
SET SHAREPASS=%%i
)
[addition by PW in response to supplementary question]
SET init=Y
SET "fields=JOB USER TEMPLATE ASSETROOT SHAREADDR SHARENAME SHAREDRIVE SHAREUSER SHAREPASS"
FOR /F "usebackq" %%a IN ("%ASSETROOT%\users\%USER%\%JOB%\prev_batch.cfg") do (
IF DEFINED init FOR %%i IN (%fields%) DO SET "%%i="
SET init=Y
FOR %%i IN (%fields%) DO IF DEFINED init IF NOT DEFINED %%i SET "%%i=%%a"&SET "init="
)
To read from sequential lines, the tokens and delims clauses are not required since there's only one string on each line BUT that one string needs to be applied to various variables.
Complicating the matter is the fact that variables that need to be set are used in the filename being read to set them.
Hence, the init flag is set non-empty initially; the variables are set once the first data line is read.
The next not-yet-set target variable is then set and the init flag cleared to ensure only one variable is set per line read.
okay, I like batch files and this one had me going for a while. You've told it that you only want %%a so that's what you're getting.
As Endoro said (I was typing the same answer when he posted), including the "tokens" keyword tells it which tokens you want.
Token %%a, obviously is the first, but by also telling the command processor that you want tokens 1-9 it separates and assigns them to next alphabetical 'variable'.
And in this case, usebackq is superfluous
There is another approach to solve this problem via an array of variable names. This method have the advantage that any modification to the list of variables (the number of variables, their names, their positions, etc) is made in a very easy way modifing just one line in the Batch file.
#echo off
setlocal EnableDelayedExpansion
rem Define the list of variable names
set variables=JOB USER TEMPLATE ASSETROOT SHAREADDR SHARENAME SHAREDRIVE SHAREUSER SHAREPASS
rem Convert the list into an array of variable names
set i=0
for %%a in (%variables%) do (
set /A i+=1
set variable[!i!]=%%a
)
set numVariables=%i%
:: Read all the arguments for this batch script from external text file
rem Version 1: Single line of text, tokens delimited with comma
set i=0
for /F "delims=" %%a in (%ASSETROOT%\users\%USER%\%JOB%\prev_batch.cfg) do (
for %%b in (%%a) do (
set /A i+=1
for %%i in (!i!) do set !variable[%%i]!=%%b
)
)
rem Version 2: Values of the variables on separate lines
set i=0
for /F "delims=" %%a in (%ASSETROOT%\users\%USER%\%JOB%\prev_batch.cfg) do (
set /A i+=1
for %%i in (!i!) do set !variable[%%i]!=%%a
)
rem Display values of all variables
for %%i in (1,1,%numVariables%) do (
for %%v in (!variable[%%i]!) do echo %%v = !%%v!
)
In the first version, the line of the file is read in %%a replaceable parameter and then processed in a for command this way:
for %%b in (%%a) do (
For example:
for %%b in (apples,oranges,bananas,grapes,strawberries) do (
Because standard Batch delimiters are space, comma, semicolon and equal-signs, the values in the list are processed one by one in the for (with NO /F option). This method allows to easily separate a list of values in individual tokens in a regular for command, but works only with the indicated delimiters.

Batch - Read contents of a file in an array

I've a text file with two rows (say param.txt) which is shown below:
Mar2012
dim1,dim2,dim3,dim4
I want to read this file in batch and store the contents of first line in a variable called cube_name. When I'm reading the second line, I want to split the comma delimited string dim1,dim2,dim3,dim4 and create an array of four elements. I am planning to use the variable and the array in later part of the script.
The code which I created is shown below. The code is not working as expected.
#echo off & setlocal enableextensions enabledelayedexpansion
set /a count_=0
for /f "tokens=*" %%a in ('type param.txt') do (
set /a count_+=1
set my_arr[!count_!]=%%a
)
set /a count=0
for %%i in (%my_arr%) do (
set /a count+=1
if !count! EQU 1 (
set cube_name=%%i
)
if !count! GTR 1 (
set dim_arr=%%i:#=,%
)
)
for %%i in (%dim_arr%) do (
echo %%i
)
echo !cube_name!
I get to see the following when I run the code:
C:\Working folder>test2.bat
ECHO is off.
So this doesn't appear to work and I can't figure out what I'm doing wrong. I am fairly new to the batch scripting so help is appreciated
Your first FOR loop is OK. It is not how I would do it, but it works. Everything after that is a mess. It looks like you think arrays are a formal concept in batch, when they are not. It is possible to work with variables in a way that looks reminiscent of arrays. But true arrays do not exist within batch.
You use %my_arr% as if it is an array, but my_arr is not even defined. You have defined variables my_arr[1] amd my_arr[2] - the brackets and number are part of the variable name.
It also looks like you have a misunderstanding of FOR loops. I suggest you carefully read the FOR documentation (type HELP FOR from a command line). Also look at examples on this and other sites. The FOR command is very complicated because it has many variations that look similar to the untrained eye, yet have profoundly different behaviors. One excellent resource to help your understanding is http://judago.webs.com/batchforloops.htm
Assuming the file always has exactly 2 lines, I would solve your problem like so
#echo off
setlocal enableDelayedExpansion
set dimCnt=0
<param.txt (
set /p "cube_name=" >nul
set /p "dimList=" >nul
for %%D in (!dimList!) do (
set /a dimCnt+=1
set "dim[!dimCnt!]=%%D"
)
)
echo cube_name=!cube_name!
for /l %%I in (1 1 !dimCnt!) do echo dim[%%I]=!dim[%%I]!
One nice feature of the above solution is it allows for a varying number of terms in the list of dimensions in the 2nd line. It will fail if there are tabs, spaces, semicolon, equal, * or ? in the dimension names. There are relatively simple ways to get around this limitation if need be.
Tabs, spaces, semicolon and equal can be handled by using search and replace to enclose each term in quotes.
for %%D in ("!dimList:,=","!") do (
set /a dimCnt+=1
set "dim[!dimCnt!]=%%~D"
)
I won't post the full solution here since it is not likely to be needed. But handling * and/or ? would require replacing the commas with a new-line character and switching to a FOR /F statement.
I'm impressed of your code!
Do you try to debug or echo anything there?
You could simply add some echo's to see why your code can't work.
#echo off & setlocal enableextensions enabledelayedexpansion
set /a count_=0
for /f "tokens=*" %%a in ('type param.txt') do (
set /a count_+=1
set my_arr[!count_!]=%%a
)
echo ### show the variable(s) beginning with my_arr...
set my_arr
echo Part 2----
set /a count=0
echo The value of my_arr is "%my_arr%"
for %%i in (%my_arr%) do (
set /a count+=1
echo ## Count=!count!, content is %%i
if !count! EQU 1 (
set cube_name=%%i
)
if !count! GTR 1 (
echo ## Setting dim_arr to "%%i:#=,%"
set dim_arr=%%i:#=,%
echo
)
)
for %%i in (%dim_arr%) do (
echo the value of dim_arr is "%%i"
)
echo cube_name is "!cube_name!"
Output is
### show the variable(s) beginning with my_arr...
my_arr[1]=Mar2012
my_arr[2]=dim1,dim2,dim3,dim4
Part 2----
The value of my_arr is ""
cube_name is ""
As you can see your part2 fails completly.

Resources