How to limit a batch variable's length - windows

Is it any way to limit the length of a batch variable? I mean, if it is possible to program a variable that only admits between 0 and x characters? So, for an instance, if I entered 123456 and the max length was 4 it wouldn't proceed to continue. I hope you can understand my question.
Thanks in advance.

Demonstration batch code according to suggestions of aschipfl and rojo:
#echo off
setlocal EnableExtensions EnableDelayedExpansion
:UserPrompt
cls
set "UserInput="
set /P "UserInput=Enter string with a length between 1 and 4: "
if not defined UserInput goto UserPrompt
if not "!UserInput:~4!" == "" goto UserPrompt
echo/
echo String entered: !UserInput!
echo/
endlocal
pause
!UserInput:~4! is replaced by command processor on execution of the batch file by the string from user input starting with fifth character. First character of a string value has index value 0 which is reason for number 4 for fifth character. This string is empty if user entered a string not longer than 4 characters, otherwise this substring is not empty resulting in user must input again a string.
Delayed expansion is used to avoid an exit of batch processing caused by a syntax error if the user enters a string containing an odd number of double quotes.
For understanding the used commands and how they work, open a command prompt window, execute there the following commands, and read entirely all help pages displayed for each command very carefully.
cls /?
echo /?
endlocal /?
if /?
pause /?
set /?
setlocal /?

If you mean "limit the length of a batch variable when it is read via SET /P command", then you may use the ReadLine subroutine described at this post, that emulates SET /P command using pure Batch file commands, and just insert the maximum length restriction.
#echo off
setlocal
call :ReadNChars string4="Enter 4 characters maximum: " 4
echo String read: "%string4%"
goto :EOF
:ReadNChars var="prompt" maxLen
rem Read a line emulating SET /P command
rem Antonio Perez Ayala
rem Initialize variables
setlocal EnableDelayedExpansion
echo > _
for /F %%a in ('copy /Z _ NUL') do set "CR=%%a"
for /F %%a in ('echo prompt $H ^| cmd') do set "BS=%%a"
rem Show the prompt and start reading
set /P "=%~2" < NUL
set "input="
set i=0
:nextKey
set "key="
for /F "delims=" %%a in ('xcopy /W _ _ 2^>NUL') do if not defined key set "key=%%a"
rem If key is CR: terminate input
if "!key:~-1!" equ "!CR!" goto endRead
rem If key is BS: delete last char, if any
set "key=!key:~-1!"
if "!key!" equ "!BS!" (
if %i% gtr 0 (
set /P "=!BS! !BS!" < NUL
set "input=%input:~0,-1%"
set /A i-=1
)
goto nextKey
)
rem Insert here any filter on the key
if %i% equ %3 goto nextKey
rem Else: show and accept the key
set /P "=.!BS!%key%" < NUL
set "input=%input%%key%"
set /A i+=1
goto nextKey
:endRead
echo/
del _
endlocal & set "%~1=%input%"
exit /B
However, if you want to limit the length of a Batch variable in other cases, like SET /A or plain SET commands, then there is no way to do that. Of course, you may execute such commands and then cut the variable value to the maximum length, but that process is an entirely different thing.

Related

Creating Each line of text as variable and them constantly changing in a loop in batch

So what I'm trying to do is create a find for multiple people where it in the text file it will say names and numbers like
Example of text file:
Beth
1234567891
Jay
2134456544
This is the best way I can explain what I'm trying to do:
#echo off
set "file=Test1.txt"
setlocal EnableDelayedExpansion
<"!file!" (
for /f %%i in ('type "!file!" ^| find /c /v ""') do set /a n=%%i && for /l %%j in (1 1 %%i) do (
set /p "line_%%j="
)
)
set /a Name=1
set /a Number=2
Echo Line_%Name%> %Name%.txt (Im trying to get this to say line_2 to say 1st line in the text file)
Echo Line_%Number%> %Name%.txt (Im trying to get this to say line_2 to say 2nd line in the text file)
:Start
set /a Name=%Name%+2 (These are meant to take off after 1 so lines 3,5,7,9 so on)
set /a Number=%Number%+2 (These are meant to take off after 2 so lines 4,6,8,10 so on)
Echo Line_%Name%
Echo Line_%Number%
GOTO :Start
so the outcome would be
In Beth.txt:
Beth
1234567891
So every name will be a file name and the first line in a file. I will change it later so I can do a addition in each text file.
Name: Beth
Number: 1234567891
#ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
SET "sourcedir=u:\your files"
SET "destdir=u:\your results"
SET "filename1=%sourcedir%\q65417881.txt"
rem make sure arrays are empty
For %%b IN (name number) DO FOR /F "delims==" %%a In ('set %%b[ 2^>Nul') DO SET "%%a="
rem Initialise counter and entry array
SET /a count=0
SET "number[0]=dummy"
FOR /f "usebackqdelims=" %%a IN ("%filename1%") DO (
IF DEFINED number[!count!] (SET /a count+=1&SET "name[!count!]=%%a") ELSE (SET "number[!count!]=%%a")
)
rem clear out dummy entry
SET "number[0]=dummy"
FOR /L %%c IN (1,1,%count%) DO (
rem replace spaces with dashes
SET "name[%%c]=!name[%%c]: =-!"
rem report to console rem report to console
ECHO Name: !name[%%c]! Number: !number[%%c]!
rem generate name.txt file
(
ECHO !name[%%c]!
ECHO !number[%%c]!
)>"%destdir%\!name[%%c]!.txt"
)
GOTO :EOF
You would need to change the values assigned to sourcedir and destdir to suit your circumstances. The listing uses a setting that suits my system.
I deliberately include spaces in names to ensure that the spaces are processed correctly.
I used a file named q65417881.txt containing your data for my testing.
The line data read from the file is assigned to %%a is assigned to and number[!count!] alternately. The data is retained in these arrays for use by further processing.
[Edited to include conversion of spaces within names to dashes]
If I understand correctly, you want to precede every second line with Number: + SPACE and every other line with Name: + SPACE. For this you do not need to store each line in a variable first, you can use a single for /F loop lo read the file line by line and process every line individually. There are two possibilities:
Temporarily precede every line with a line number plus : using findstr /N:
#echo off
rem // Loop through lines and precede each with line number plus `:`:
for /F "tokens=1* delims=:" %%K in ('findstr /N "^" "Test1.txt"') do (
rem // Calculate remainder of division by two:
set /A "MOD=%%K%%2" 2> nul
rem // Toggle delayed expansion to avoid issues with `!`:
setlocal EnableDelayedExpansion
rem // Conditionally return line string with adequate prefix:
if !MOD! neq 0 (
endlocal & echo Name: %%L
) else (
endlocal & echo Number: %%L
)
)
This will fail when a line begins with the a :.
Check whether numeric representation of current line string is greater than 0:
#echo off
rem // Loop through (non-empty) lines:
for /F "usebackq delims=" %%L in ("Test1.txt") do (
rem // Determine numeric representation of current line string:
set /A "NUM=%%L" 2> nul
rem // Toggle delayed expansion to avoid issues with `!`:
setlocal EnableDelayedExpansion
rem // Conditionally return line string with adequate prefix:
if !NUM! equ 0 (
endlocal & echo Name: %%L
) else (
endlocal & echo Number: %%L
)
)
This fails when a name begins with numerals and/or when a numeric line is 0.
And just for the sake of posting something different:
#SetLocal EnableExtensions DisableDelayedExpansion & (Set LF=^
% 0x0A %
) & For /F %%G In ('Copy /Z "%~f0" NUL') Do #Set "CR=%%G"
#For /F "Tokens=1,2* Delims=:" %%G In ('%__AppDir__%cmd.exe /D/V/C ^
"%__AppDir__%findstr.exe /NR "^[a-Z]*!CR!!LF![0123456789]" "Test1?.txt" 2>NUL"
') Do #(SetLocal EnableDelayedExpansion
(Set /P "=Name: %%I!CR!!LF!Number: " 0<NUL & Set "_="
For /F Delims^=^ EOL^= %%J In ('%__AppDir__%more.com +%%H "%%G"') Do #(
If Not Defined _ Set "_=_" & Echo %%J)) 1>"%%I.txt" & EndLocal)
This file should be run with the Test1.txt file in the current working directory. It is important that along side Test1.txt, there are no other .txt files with the same basename followed by one other character, (for example Test1a.txt or Test12.txt). Should you wish to change your filename, just remember that you must suffix its basename in the above code with a ? character, (e.g. MyTextFile.log ⇒ MyTextFile?.log).
I had the rare opportunity to verify that this script worked against the following example Test1.txt file:
Beth
1234567891
Jay
2134456544
Bob
2137856514
Jimmy
4574459540
Mary
3734756547
Gemma
6938456114
Albert
0134056504

Batch file error "/100 was unexpected at this time"

I make a game for fun with batch script but in this code i have an error message "/100 unexpected at this time" i really don't understand why? Please help me!!
#echo off
mode con cols=110 lines=32
setlocal enabledelayedexpansion
set npctier=0
goto randomnpc
:randomnpc
if %npctier% EQU 0 (
set npctype=Wooden Dummy
set /a npclvl=%random% %% 5+1
set /a npchp=%npclvl% * 100
set /a npcdmg=0
set /a npcdef=(%npchp%*5)/100
set /a npcxp=%npclvl%*100 )
:combatchoice
echo.
echo. You see %npctype% level %npclvl%.
echo.
echo. The %npctype%'s Health: %npchp% HP
echo.
goto main
I recommend to first open a command prompt, run set /? and read the output help carefully and completely from top of first to bottom of last page. There is explained:
Any non-numeric strings in the expression are treated as environment variable names whose values are converted to numbers before using them. If an environment variable name is specified but is not defined in the current environment, then a value of zero is used. This allows you to do arithmetic with environment variable values without having to type all those % signs to get their values.
So there can be written just set /A npchp=npclvl * 100 as npclvl inside the arithmetic expression is interpreted as name of an environment variable and the command line works even on being inside a command block starting with ( and ending with matching ) without usage of delayed environment variable expansion.
Then run cmd /? and read again the output help carefully and completely from top of first to bottom of last page. There is explained that a file name (or any other argument string) containing a space one of these characters &()[]{}^=;!'+,`~ must be enclosed in " to get those characters interpreted as literal characters of an argument string.
Please read also How does the Windows Command Interpreter (CMD.EXE) parse scripts?
For that reason the command line set /a npcdef=(%npchp%*5)/100 should be written with one of the following notations:
set /A npcdef=npchp*5/100
set /A npcdef=npchp * 5 / 100
set /A "npcdef=(npchp*5)/100"
set /A npcdef=(npchp*5^)/100
The caret character ^ escapes the next character for being interpreted as literal character except the next character is % which must be escaped with %.
The recommendations posted on DosTips forum topic ECHO. FAILS to give text or blank line - Instead use ECHO/ should be also taken into account on writing batch files which output empty lines.
The batch file with the main improvement of changing the IF condition to avoid completely the usage of a command block.
#echo off
setlocal EnableExtensions DisableDelayedExpansion
%SystemRoot%\System32\mode.com con cols=110 lines=32
set npctier=0
set "npctype=Wooden Dummy"
:randomnpc
if %npctier% NEQ 0 goto CombatChoice
set /A npclvl=%random% %% 5 + 1
set /A npchp=npclvl*100
set npcdmg=0
set /A npcdef=npchp*5/100
set /A npcxp=npclvl*100
:CombatChoice
echo/
echo You see %npctype% level %npclvl%.
echo/
echo The %npctype%'s health: %npchp% HP
echo/
endlocal
See also Why is no string output with 'echo %var%' after using 'set var = text' on command line? It contains several hints on how to use command SET not written in help/documentation of this command.
If you wish to maintain the same structure, then something lke this would be better:
#Echo Off
SetLocal EnableExtensions
%__APPDIR__%mode.com 110, 32
Set "npctier=0"
:randomnpc
If %npctier% Equ 0 (
Set "npctype=Wooden Dummy"
Set "npcdmg=0"
Set /A "npclvl=(%RANDOM% %% 5) + 1"
Set /A "npchp=npclvl * 100, npcdef=npclvl * 5, npcxp=npchp"
)
:combatchoice
Echo=
Echo You see %npctype% level %npclvl%.
Echo=
Echo The %npctype%'s Health: %npchp% HP
Echo=
GoTo main
You should note, that it is possible to define multiple values using Set /A in one arithmetic instruction
Before you get too carried away with creating a lengthy script which repeats code, I think it's worthwhile introducing you to batch macro's.
Macro's in Batch are commands or command blocks assigned to variables, and through the use of For loops combined with If / Else conditioning can be used to Capture arguments allowing variables to be used as Functions.
The below example contains two variations of a macro that can be used to easily generate different encounter types with minimal repetative scripting whilst also avoiding the use of inefficient calls to functions.
Macro's must be defined prior to delayed expansion being enabled as variables referenced during macro execution are defined using ! expansion so that the value the macro is parsed with at expansion is the value of the variable at the time of parsing, not it's value during definition.
#echo off
mode con cols=110 lines=32
(Set \n=^^^
%= macro newline DNR =%
)
(Set LF=^
%= Linefeed DNR =%)
rem Example 1: npc generation; Fixed Formula macro
rem USAGE: %npc{generic}%{Npc name / type}{npc max level}{npc multiplier}{damage value or formula}
Set npc{generic}=For %%n in (1 2)Do if %%n==2 (%\n%
For /F "Tokens=1,2,3,4 Delims={}" %%G in ("!Params!")Do (%\n%
Set "npctype=%%G" %\n%
Set /a "npclvl= !random! %% %%H + 1" %\n%
Set /a "npchp= !npclvl! * %%I" %\n%
Set /a "npcdmg= %%J" %\n%
Set /a "npcdef= ( !npchp! * %%H ) / %%I" %\n%
Set /a "npcxp=!npclvl! * %%I" %\n%
echo/Enemy: !npctype!!LF!level: !npclvl!!LF!HP: !npchp!!LF!Damage: !npcdmg!!LF!Defence: !npcdef!!LF!XP: !npcxp!!LF!%\n%
)%\n%
) Else Set Params=
rem Example 2: npc generation; Supplied Formula macro
rem USAGE: %npc{boss}%{Npc name / type}{level value or formula}{hp value or formula}{damage value or formula}{defense value or formula}{xp value or formula}
Set npc{boss}=For %%n in (1 2)Do if %%n==2 (%\n%
For /F "Tokens=1,2,3,4,5,6 Delims={}" %%G in ("!Params!")Do (%\n%
Set "npctype=%%G" %\n%
Set /a "npclvl= %%H " %\n%
Set /a "npchp= %%I " %\n%
Set /a "npcdmg= %%J " %\n%
Set /a "npcdef= %%K " %\n%
Set /a "npcxp= %%L " %\n%
echo/Enemy: !npctype!!LF!level: !npclvl!!LF!HP: !npchp!!LF!Damage: !npcdmg!!LF!Defence: !npcdef!!LF!XP: !npcxp!!LF!%\n%
)%\n%
) Else Set Params=
rem enable delayed expansion after macro definitions
setlocal enableextensions enabledelayedexpansion
:randomnpc
%npc{generic}%{Wooden Dummy}{5}{100}{0}
Pause
%npc{boss}%{Dragon}{!random! %% 10 + 10}{npclvl * 200}{npchp / 20}{npchp / (npclvl / 2)}{npclvl * 150}
Endlocal
Goto :Eof

Count number of letters in CMD and batchfile

I have this project using batch file.My code below can count characters when user type inputs (numbers, letters, symbols),but i want the program count only letters. Can you help me out with this problem. My code is shown below.
#ECHO OFF
echo.
:a
REM Set "string" variable
SET /p string="Type characters to Count:"
REM Set the value of temporary variable to the value of "string" variable
SET temp_str=%string%
REM Initialize counter
SET str_len=1
:loop
if defined temp_str (
REM Remove the first character from the temporary string variable and increment
REM counter by 1. Countinue to loop until the value of temp_str is empty string.
SET temp_str=%temp_str:~1%
SET /A str_len += 1
GOTO loop
)
REM Echo the actual string value and its length.
ECHO %string% is %str_len% characters long!
set /p prompt="Do you want to continue?Y/N:"
if %prompt%==Y goto a
goto b
:b
pause
exit
#ECHO OFF
setlocal enableextensions disabledelayedexpansion
:getString
echo(
REM Set "string" variable
set "string="
SET /p "string=Type characters to Count:"
:calculateLength
if not defined string ( set "str_len=0" ) else (
for /f %%a in ('
cmd /u /v /q /c"(echo(!string!)" %= output unicode string =%
^| find /v "" %= separate lines =%
^| findstr /r /c:"[a-zA-Z]" %= filter characters =%
^| find /c /v "" %= count remaining lines =%
') do set "str_len=%%a"
)
:show
REM Echo the actual string value and its length.
ECHO [%string%] is %str_len% letters long!
echo(
set /p "prompt=Do you want to continue? Y/n: " || set "prompt=Y"
if /i "%prompt%"=="Y" goto :getString
pause
exit /b
This uses a simple trick. If we start a unicode cmd instance, its output (the result from echo in this case) is unicode, that is, two bytes per character, usually a null and the real character.
This output is processed by a filter, more or find, that will process the nulls as line terminators, splitting the output string into lines, one line for each input character.
This set of lines are filtered with findstr to only allow letters. The remaining lines are counted with a find /c /v "" command that will count non empty lines.
edited to adapt to comments.
Input a block of lines and process them
#ECHO OFF
setlocal enableextensions disabledelayedexpansion
set "tempFile=%temp%\%random%%random%%random%.tmp"
:getString
echo(
echo(Please, type your text and end input pressing F6 and Enter
copy con "%tempfile%" >nul 2>nul
:calculateLength
for /f %%a in ('
cmd /u /q /c"(type "%tempFile%")" %= output unicode string =%
^| find /v "" %= separate lines =%
^| findstr /r /c:"[a-zA-Z]" %= filter characters =%
^| find /c /v "" %= count remaining lines =%
') do set "str_len=%%a"
:show
ECHO input data is %str_len% letters long!
echo(
del /q "%tempFile%" 2>nul
set /p "prompt=Do you want to continue? Y/n: " || set "prompt=Y"
if /i "%prompt%"=="Y" goto :getString
pause
exit /b
You are setting initial string length to 1 in line
SET str_len=1
change it to 0 like so:
SET str_len=0
#ECHO OFF
setlocal EnableDelayedExpansion
REM Define a string with all letters:
SET letters=ABCDEFGHIJKLMNOPQRSTUVWXYZ
echo.
:a
REM Set "string" variable
SET /p string="Type characters to Count:"
REM Set the value of temporary variable to the value of "string" variable
SET temp_str=%string%
REM Initialize counter
SET str_letters=0
:loop
if defined temp_str (
REM Get the first character from temporary string variable
SET char=%temp_str:~0,1%
REM If the character is letter, count it
if "!letters:%char%=!" neq "%letters%" SET /A str_letters += 1
REM Remove the first character from the temporary string variable.
REM Countinue to loop until the value of temp_str is empty string.
SET temp_str=%temp_str:~1%
GOTO loop
)
REM Echo the actual string value and its number of letters.
ECHO %string% have %str_letters% letters
set /p prompt="Do you want to continue?Y/N:"
if %prompt%==Y goto a
goto b
:b
pause
exit

LastIndexOf in Windows batch

I need to implement a function in a Windows batch script to get the LastIndexOf a character into a given string.
For example: Given the following string, I need to get the last index of character '/':
/name1/name2/name3
^
So I need to get the value:
12
Joey's solution works, but the character to find is hard coded, and it is relatively slow.
Here is a parametized function that is fast and can find any character (except nul) within the string. I pass the name of variables containing the string and the character instead of string literals so that the function easily supports all characters.
#echo off
setlocal
set "test=/name1/name2/name3"
set "char=/"
::1st test simply prints the result
call :lastIndexOf test char
::2nd test stores the result in a variable
call :lastIndexOf test char rtn
echo rtn=%rtn%
exit /b
:lastIndexOf strVar charVar [rtnVar]
setlocal enableDelayedExpansion
:: Get the string values
set "lastIndexOf.char=!%~2!"
set "str=!%~1!"
set "chr=!lastIndexOf.char:~0,1!"
:: Determine the length of str - adapted from function found at:
:: http://www.dostips.com/DtCodeCmdLib.php#Function.strLen
set "str2=.!str!"
set "len=0"
for /L %%A in (12,-1,0) do (
set /a "len|=1<<%%A"
for %%B in (!len!) do if "!str2:~%%B,1!"=="" set /a "len&=~1<<%%A"
)
:: Find the last occurrance of chr in str
for /l %%N in (%len% -1 0) do if "!str:~%%N,1!" equ "!chr!" (
set rtn=%%N
goto :break
)
set rtn=-1
:break - Return the result if 3rd arg specified, else print the result
( endlocal
if "%~3" neq "" (set %~3=%rtn%) else echo %rtn%
)
exit /b
It wouldn't take much modification to create a more generic :indexOf function that takes an additional argument specifying which occurance to find. A negative number could specify to search in reverse. So 1 could be the 1st, 2 the 2nd, -1 the last, -2 penultimate, etc.
(Note: I'm assuming Windows batch files because, frankly, I have only seen a single question asking for an actual DOS batch file here so far. Most people simply misattribute “DOS” to anything that has a window of gray-on-black monospaced text without knowing what they're actually talking of.)
Just loop through it, updating the index as you go:
#echo off
setlocal enabledelayedexpansion
set S=/name1/name2/name3
set I=0
set L=-1
:l
if "!S:~%I%,1!"=="" goto ld
if "!S:~%I%,1!"=="/" set L=%I%
set /a I+=1
goto l
:ld
echo %L%
I know this question is a bit old now, but I needed a function that could find the location of a substring (of any length) within a string, and adapted dbenham's solution for my purposes. This function also works with individual characters within a string, as asked for in the original question, and can search for specific instances (as suggested by dbenham).
To use this function, the actual strings must be passed. Dbenham does note that this supports fewer characters than passing the actual variables, but I find that this variant is more reuseable (especially with pipes).
The third argument takes the instance that should be found, with negative numbers specifying to search from the end. The index returned is the offset from the start of the string to the first character in the substring.
#ECHO off
SET search_string=sub
CALL :strIndex "The testing subjects subjects to testing." "%search_string%" -2
ECHO %ERRORLEVEL%
PAUSE
EXIT
:strIndex string substring [instance]
REM Using adaptation of strLen function found at http://www.dostips.com/DtCodeCmdLib.php#Function.strLen
SETLOCAL ENABLEDELAYEDEXPANSION
SETLOCAL ENABLEEXTENSIONS
IF "%~2" EQU "" SET Index=-1 & GOTO strIndex_end
IF "%~3" EQU "" (SET Instance=1) ELSE (SET Instance=%~3)
SET Index=-1
SET String=%~1
SET "str=A%~1"
SET "String_Length=0"
FOR /L %%A IN (12,-1,0) DO (
SET /a "String_Length|=1<<%%A"
FOR %%B IN (!String_Length!) DO IF "!str:~%%B,1!"=="" SET /a "String_Length&=~1<<%%A"
)
SET "sub=A%~2"
SET "Substring_Length=0"
FOR /L %%A IN (12,-1,0) DO (
SET /a "Substring_Length|=1<<%%A"
FOR %%B IN (!Substring_Length!) DO IF "!sub:~%%B,1!"=="" SET /a "Substring_Length&=~1<<%%A"
)
IF %Substring_Length% GTR %String_Length% GOTO strIndex_end
SET /A Searches=%String_Length%-%Substring_Length%
IF %Instance% GTR 0 (
FOR /L %%n IN (0,1,%Searches%) DO (
CALL SET StringSegment=%%String:~%%n,!Substring_Length!%%
IF "%~2" EQU "!StringSegment!" SET /A Instance-=1
IF !Instance! EQU 0 SET Index=%%n & GOTO strIndex_end
)) ELSE (
FOR /L %%n IN (%Searches%,-1,0) DO (
CALL SET StringSegment=%%String:~%%n,!Substring_Length!%%
IF "%~2" EQU "!StringSegment!" SET /A Instance+=1
IF !Instance! EQU 0 SET Index=%%n & GOTO strIndex_end
))
:strIndex_end
EXIT /B %Index%

Help in writing a batch script to parse CSV file and output a text file

I am struggling to write a batch script which can read a CSV file such as below
Name:, City:, Country:
Mark, London, UK
Ben, Paris, France
Tom, Athens, Greece
There will be a heading row in the CSV file. It should output to a text file as below:
Name:Mark
City:London
Country:UK
Name:Ben
City:Paris
Country:France
Name:Tom
City:Athens
Country:Greece
The field separator (:) in the above output is expected to be provided in the header row itself. So all that I need to do is concatenate the field heading and its value.
The number of columns in this CSV file is not fixed, so the script should not limit to 3 tokens. Kindly help!
#ECHO OFF
IF "%~1"=="" GOTO :EOF
SET "filename=%~1"
SET fcount=0
SET linenum=0
FOR /F "usebackq tokens=1-10 delims=," %%a IN ("%filename%") DO ^
CALL :process "%%a" "%%b" "%%c" "%%d" "%%e" "%%f" "%%g" "%%h" "%%i" "%%j"
GOTO :EOF
:trim
SET "tmp=%~1"
:trimlead
IF NOT "%tmp:~0,1%"==" " GOTO :EOF
SET "tmp=%tmp:~1%"
GOTO trimlead
:process
SET /A linenum+=1
IF "%linenum%"=="1" GOTO picknames
SET ind=0
:display
IF "%fcount%"=="%ind%" (ECHO.&GOTO :EOF)
SET /A ind+=1
CALL :trim %1
SETLOCAL ENABLEDELAYEDEXPANSION
ECHO !f%ind%!!tmp!
ENDLOCAL
SHIFT
GOTO display
:picknames
IF %1=="" GOTO :EOF
CALL :trim %1
SET /a fcount+=1
SET "f%fcount%=%tmp%"
SHIFT
GOTO picknames
This batch scipt:
accepts one parameter, the name of the file to process;
does not verify the presence of : at the end of a header token, and when the values are displayed they are placed immediately after the corresponding header tokens;
trims all the leading spaces (but not the trailing ones);
considers the first row to be the header row, which also defines the number of tokens to process in subsequent rows;
supports up to 10 tokens, and the two areas highlighted in bold italics are responsible for that (so when you need to change the maximum number, modify both areas: if you increase the number, you must expand the "%%a" "%%b" "%%c" … list, and, likewise, if you decrease the number, then shrink the list).
I know this is an old question, but this type of question is my favorite one so here it is my answer:
#echo off
setlocal EnableDelayedExpansion
rem Create heading array:
set /P headingRow=< %1
set i=0
for %%h in (%headingRow%) do (
set /A i+=1
set heading[!i!]=%%~h
)
rem Process the file:
call :ProcessFile < %1
exit /B
:ProcessFile
set /P line=
:nextLine
set line=:EOF
set /P line=
if "!line!" == ":EOF" goto :EOF
set i=0
for %%e in (%line%) do (
set /A i+=1
for %%i in (!i!) do echo !heading[%%i]!%%~e
)
goto nextLine
exit /B
This program have not any limit in the number of fields. This version requires to enclose in quotes the elements that may have spaces or other Batch delimiters, but this restriction may be easily fixed.
Python makes this so easy it should be regulated by the government.
from csv import DictReader
with open('file', 'rb') as file:
reader = DictReader(file)
for line in reader:
for field in reader.fieldnames:
print '{0}{1}'.format(field.strip(), line[field].strip())
print '\n'
Edit: I guess you need something native to the Windows command shell. Oh well.

Resources