3

I have a question with the "for" batch command in windows.

I have a file called keys.txt which contains this line..

key,value,x86,windows7

I want to parse this line and store the 4 comma seperated variables in 4 variables. I accomplish that by the following windows batch script.

 for /F "tokens=1,2,3,4* delims=," %%i
 in (keys.txt) do (

    echo first is %%i

    echo second is %%j

    echo third is %%k

    echo fourth is %%l

    echo rest is %%m

    echo -------------  

 )

However, when i modify the keys.txt to

key,value,,windows7

The third variable is printed as windows7. I would expect the 3rd variable to be empty and the 4th variable to be windows7. If i give a space between the 2 comma's like this

key,value, ,windows7

Then it prints the 3rd variable as empty and the 4th variable as Windows7.

Anyone knows how i can make the earlier case (i.e the one without the space) also to work correctly?

2
  • Why use batch to parse files? Do you have other options? like using a real file parser (language) ? If you can't download and use stuff, you can use vbscript, which is better at doing such jobs. Commented Aug 26, 2010 at 13:24
  • Actually, there is a lot of code written using batch scripts, so it would be a huge task to migrate the whole thing to vbs. However, i found another alternative which would be to write a vbs file that would create a file with a list of set var=value lines and then call this batch file from the parent batch file. Commented Aug 27, 2010 at 7:27

3 Answers 3

4

Try this. Idea fom here
The script preprocess each line assigning the text #NUL# to each empty slot. You can disregard #NUL# values after that.

cls
setlocal enabledelayedexpansion
@echo off
for /f "tokens=*" %%X in (keys.txt) do (
    set "work=%%X"
    :: fill empty fields with "#NUL#" ...
    :: but do it twice, just in case consecutive fields are empty
    for /l %%i in (1,1,2) do set "work=!work:,,=,#NUL#,!"
    for /F "tokens=1,2,3,4* delims=," %%i in ("!work!") do (
echo first is %%i
echo second is %%j
echo third is %%k
echo fourth is %%l
echo rest is %%m
echo -------------  
))

HTH

Sign up to request clarification or add additional context in comments.

Comments

1

for is designed to not preserve null/empty tokens on some systems, so allocates next next token to the placeholder (as long as it's also not null/empty). This also happens when printing text with leading space or blank lines on some versions of Windows™. To work around this, preprocess the data and fill some value in empty data eg. space (as you've experimented) to preserve all tokens.

for /f "delims=" %a in (test.1) do set data=%a& set data=!data:,=","!& for /f "tokens=1-4 delims=," %i in ("!data!") do set a=%i-%j-%k-%l& echo !a:"=!

The above code preprocesses data similar to CSV format, which also works with data containing spaces within same 'cell'. eg. output: key-value--windows 7

If your data contains the delimiter , and you want it preserved as part of data, then change the delimiter in the for or escape it during preprocessing.

Update (a practical application for mass processing):
With this method you can also autofill (common)data eg. if you're processing multiple files and file names are to be read from a template file, then instead of typing file names on command prompt for every file to be processed, you can create a template file and read file names from it.

If most of them have a common extension eg. .txt, then just type ,, (blank data) instead of typing .txt everytime, like so:

file1,,
file 2,,
file 3la,,
different file,.pdf

Then in your code, the blank spaces ,, will be prefilled with .txt (saving time creating the template file).

Here's the code for preprocessing file names before being fed to main process code:

for /f "delims=" %a in (test.1) do set data=%a& set data=!data:,=","!& for /f "tokens=1,2 delims=," %i in ("!data!") do (
REM replace empty cells with ".txt"
echo %j | find "." >nul && (set j=%j) || set j=.txt
set data=%i!j! & echo !data:"=!
)

Comments

0

For it to work with tab -separated values I did the following, as a modification to Dr. belisarius' answer:

@echo off
setlocal enabledelayedexpansion

for /f "tokens=* delims=<TAB>" %%X in (keys.txt) do (
  set "work=%%X"
  for /l %%i in (1,1,3) do set "work=!work:<TAB><TAB>=<TAB>#NUL#<TAB>!"
  for /F "tokens=1,2,3,4* delims=<TAB>" %%i in ("!work!") do (
echo first is %%i
echo second is %%j
echo third is %%k
echo fourth is %%l
echo rest is %%m
echo -------------  
))
pause >nul

, with <tab> being replaced by the real tab -value

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.