# batch file to read from input file



## jpmg

Hello. I'm having trouble with the FOR command syntax to read lines of an input file into separate variables and I was hoping you can help.

Suppose an input file had
Var1: a
Var2: b

what is the syntax in a batch file to set the variable Var1 to the value "a" and the variable Var2 to the value "b" ? It seems like a common enough need, but I couldn't find many examples out there...

Thanks
Jason


----------



## techjed

@echo off
set Var1=a
echo %Var1%
pause


the above batch will set the "variable" Var1 to ALWAYS equal "a". 

when you refer to Var1, you usually use %% around it... 

help any?

techjed


----------



## jpmg

Hello,

that's not exactly what I meant. Suppose we have a configuration file, a text file config.txt that has
var1: a
var2: b

Then, we have second file, the batch file, that is invoked by
> RunBathFile config.txt

What I am looking for is the syntax, in RunBatchFile.bat, that will read the contents of config.txt and assign the var1 variable in RunBatchFile to the value a and set the var2 variable in RunBatchFile to the value b, based on a read of config.txt.

Any ideas?
Thanks


----------



## TheOutcaste

Welcome to TSG!
Several ways to do this, depends on how the data in config.txt is formatted, if you need the variables to stay defined when the batch file ends, and if you have more than one set of data to read in.

*#1:*


Code:


@Echo Off
SetLocal EnableDelayedExpansion
::This line is just in case n has been defined before the batch file is run
Set n=
Set _InputFile=c:\test1\config.txt
For /F "tokens=*" %%I IN (%_InputFile%) DO (
Set /a n+=1
Set _var!n!=%%I
)
:: This line will display the variables just assigned
:: For testing only, delete when not needed
Set _
EndLocal

This assumes the data for each variable is on a separate line in config.txt. (carriage return/linefeed is delimiter) This means spaces and tabs are allowed. The exclamation point (*!*) must be "escaped" with a caret (*^*) or it will be ignored, as will everything after an *!* until a *"* or another *!*. The caret must also be escaped, so use *^^* or *^!* instead of *^* or *!*.
The FOR loop just reads in the data, all processing must be done after the FOR loop ends.
Number of variables is limited by memory (how many I don't know). They will be deleted when the batch file ends. If you need them to persist, you need to use the method 2 or 3, or remove the Setlocal and Endlocal lines *AND* enable *Delayed environment variable expansion* by starting the command prompt with *cmd /V:ON* or by editing the registry -- see cmd /? for the registry values
If config.txt contains this:


Code:


apple cart
basket of oranges^!
100
22

it will produce this:


Code:


 _InputFile=c:\test1\config.txt
_var1=apple cart
_var2=basket of oranges!
_var3=100
_var4=22

*#2:*


Code:


@Echo Off
Set _InputFile=c:\test1\config.txt
For /F "tokens=[COLOR=Red]1-4[/COLOR]* delims=," %%A IN (%_InputFile2%) DO (
Set _var1=%%A
Set _var2=%%B
Set _var3=%%C
Set _var4=%%D
Set _var5=%%E
)
:: This line will display the variables just assigned
:: For testing only, delete when not needed
Set _

All the data for each iteration of the FOR loop must be on one line in the file, separated by commas (you can pick a different delimiter). You are limited to 26 variables. The *tokens=1-4** line must be adjusted to match the number of data items you want to use. Instead of a range, you can specify each token, ie *tokens=1,3,5*. The * if used will assign the remainder of the line to an additional variable.
Use this method if you have multiple sets of data to work with. The FOR loop will read one line, assign data to variables, then you can process the variables. The FOR loop will then read the next line, and repeat the process.
The variables will remain defined with the data from the last line of the config.txt after the batch file ends. You can use *setlocal* (without the EnableDelayedExpansion part) and *endlocal* if you don't need them to remain defined.
If config.txt contains this:


Code:


apple cart,basket of oranges^!,100,22,More stuff,last item in the file

it will produce this:


Code:


 _InputFile=c:\test1\config.txt
_var1=apple cart
_var2=basket of oranges!
_var3=100
_var4=22
_var5=More stuff,last item in the file

*#3:*
This one is useful if you need your data file (config.txt) to be somewhat human readable. The format of the data file is:
* line number:label:data*



Code:


@Echo Off
Set _InputFile=c:\test1\config.txt
For /F "tokens=1,2* delims=:" %%A IN (%_InputFile%) DO Set _Data[COLOR=Purple]%%A[/COLOR]=[COLOR=Orange]%%C[/COLOR]
:: This line will display the variables just assigned
:: For testing only, delete when not needed
Set _
EndLocal

This is similar to Method 1, but you don't need to enable *Delayed environment variable expansion*.
So, if config.txt contains this:


Code:


1:type and method of transport for first item:apple cart
2:type and method of transport for 2nd item:basket of oranges^!
3:weight of first item:100
4:weight of second item:22

it will produce this:


Code:


 _InputFile=c:\test1\config.txt
_Data1=apple cart
_Data2=basket of oranges!
_Data3=100
_Data4=22

If you wish to specify the config.txt file on the command line (RunBathFile config.txt) rather than defining it in the file, change the *Set _InputFile=* line to this:
*Set _InputFile=%1*
If your config file name contains spaces (i.e, config data.txt) you'll need to surround it in quotes, or use *%** instead of *%1*

HTH

Jerry


----------



## zxuesg

eg 

sx100 sx200 sx300
fx100, nil, fx700


----------



## TheOutcaste

Welcome to TSG!



zxuesg said:


> eg
> 
> sx100 sx200 sx300
> fx100, nil, fx700





TheOutcaste said:


> *#2:*
> 
> 
> Code:
> 
> 
> @Echo Off
> Set _InputFile=c:\test1\config.txt
> For /F "tokens=[COLOR=Red]1-4[/COLOR]* delims=," %%A IN (%_InputFile2%) DO (
> Set _var1=%%A
> Set _var2=%%B
> Set _var3=%%C
> Set _var4=%%D
> Set _var5=%%E
> )
> :: This line will display the variables just assigned
> :: For testing only, delete when not needed
> Set _
> 
> All the data for each iteration of the FOR loop must be on one line in the file, separated by commas (you can pick a different delimiter).


Just change the *delims=,"* to *delims "* to use a space.
For the comma separated, if you can't remove the space after the comma, you'll get this:
_var1=fx100
_var2= nil
_var3= fx700
_var4= fx900
_var5=

Note the leading space on 2-4; to remove the space you have a couple of options. If there will *always* be a space after the comma, you can just remove the first character for variables #2 and up like this:
* Set _tmp2=!_tmp2:~1!*
If you are not sure if there will be a space, use an if statement:
* If "!_tmp2:0,1!==" " then Set _tmp2=!_tmp2:~1!*
You can also use a For loop to check as well:


Code:


[B]For /L %%a IN (1,1,5) Do If "!_tmp%%a:~0,1!"==" " Set _tmp%%a=!_tmp%%a:~1![/B]

If none of the data contains spaces you can use *delims= ,"* (space followed by comma) but if there are spaces you'll get the wrong result:
This:
* fx100, nil, fx 700, fx900*
Will assign the following:
* _var1=fx100
_var2=nil
_var3=fx
_var4=700
_var5=fx900*

Instead of:
* _var1=fx100
_var2=nil
_var3=fx 700
_var4=fx900
_var5=*

HTH

Jerry


----------



## ghostdog74

if you want to parse a data file, use something better than batch, such as vbscript( or others like Perl/Python/sed/gawk ). These tools are better suited to do such tasks. Here's a vbscript 


Code:


Set objFS = CreateObject("Scripting.FileSystemObject")
strFile = "C:\test\test.txt"
Set objFile = objFS.OpenTextFile(strFile,1)
Do Until objFile.AtEndOfStream
	strLine = objFile.ReadLine
	arrayA = Split(strLine,":")
	' now arrayA(0) contains var1 value and arrayA(1) contains var2 value
	WScript.Echo arrayA(0), arrayA(1) 
Loop

you can also use dictionary object



Code:


Set objFS = CreateObject("Scripting.FileSystemObject")
Set d = CreateObject("Scripting.Dictionary")
strFile = "C:\test\test.txt"
Set objFile = objFS.OpenTextFile(strFile,1)
Do Until objFile.AtEndOfStream
	strLine = objFile.ReadLine
	arrayA = Split(strLine,":")
	d.Add arrayA(0),arrayA(1)
Loop
a = d.Items   ' Get the items.
b = d.Keys
For i = 0 To d.Count -1 ' Iterate the array.
  WScript.Echo b(i) , a(i)  
Next


----------

