Computing.Net > Forums > Programming > Batch programming question

Batch programming question

Reply to Message Icon

Original Message
Name: klint
Date: November 9, 2007 at 11:12:15 Pacific
Subject: Batch programming question
OS: Windows XP
CPU/Ram: n/a
Model/Manufacturer: n/a
Comment:

I am trying to iterate through an semicolon-separated environment variable, such as PATH, CLASSPATH, INCLUDE, LIB, etc. This variable is given to the script as a command-line argument. I have already done this in Python, Perl, and Awk, and it's quite easy in those languages. However, I also tried to do it in cmd.exe language, like a masochist, without using any external commands. This is what I've come up with:

@echo off
setlocal EnableDelayedExpansion

if not "%1"=="" if not "%1"=="?" if not "%1"=="/?" if not "%1"=="-h" if not "%1"=="--help" if "%2"=="" goto :doit

echo Usage: %0 environment_variable
exit /b 1

:doit
for /f "tokens=1-25* delims=;" %%a in ("!%1!") do (
if not "%%a"=="" echo %%a
if not "%%b"=="" echo %%b
if not "%%c"=="" echo %%c
if not "%%d"=="" echo %%d
if not "%%e"=="" echo %%e
if not "%%f"=="" echo %%f
if not "%%g"=="" echo %%g
if not "%%h"=="" echo %%h
if not "%%i"=="" echo %%i
if not "%%j"=="" echo %%j
if not "%%k"=="" echo %%k
if not "%%l"=="" echo %%l
if not "%%m"=="" echo %%m
if not "%%n"=="" echo %%n
if not "%%o"=="" echo %%o
if not "%%p"=="" echo %%p
if not "%%q"=="" echo %%q
if not "%%r"=="" echo %%r
if not "%%s"=="" echo %%s
if not "%%t"=="" echo %%t
if not "%%u"=="" echo %%u
if not "%%v"=="" echo %%v
if not "%%w"=="" echo %%w
if not "%%x"=="" echo %%x
if not "%%y"=="" echo %%y
if not "%%z"=="" echo %%z
)


The problem is, how do I turn the long sequence into an iteration? I tried, but run into problems caused by the fact that many elements (between the semicolons) in the given variable contain spaces and/or quotation marks.

One possibility I've thought of was to use the substitution syntax:

%VAR:old=new%

But how can I replace the ';' character with the newline character?



Report Offensive Message For Removal

Response Number 1
Name: Razor2.3
Date: November 9, 2007 at 12:01:40 Pacific
Subject: Batch programming question
Reply: (edit)

Am I missing something here? Would someone who doesn't have Vista check to see if your CMD will break apart command line arguments by the semicolon?

Here's what I'm getting:
Fri 11/09/2007 14:54:54.41
C:\Users\usr>copy con a.bat
@echo %1^Z

1 file(s) copied.

Fri 11/09/2007 14:55:06.31
C:\Users\usr>a asdf;asfd
asdf


Report Offensive Follow Up For Removal

Response Number 2
Name: tonysathre
Date: November 9, 2007 at 14:13:58 Pacific
Subject: Batch programming question
Reply: (edit)

XP breaks them apart just the same.

"Computer security." — Oxymoron


Report Offensive Follow Up For Removal

Response Number 3
Name: Razor2.3
Date: November 9, 2007 at 14:35:32 Pacific
Subject: Batch programming question
Reply: (edit)

Well then, assuming the OP's string doesn't include spaces, he could do the following:

@ECHO OFF
:loop
ECHO %1
SHIFT
IF NOT "%1"=="" GOTO loop


Report Offensive Follow Up For Removal

Response Number 4
Name: klint
Date: November 10, 2007 at 09:15:34 Pacific
Subject: Batch programming question
Reply: (edit)

I know, but unfortunately it is very likely to contain spaces. The string could, for example, be %PATH%. Let's say it's
"C:\Windows\system32;C:\Program Files\Executables;C:\Documents and Settings\klint\My Documents\bin". Then I would run this batch file by typing:

C:\> showvar PATH

and it would print out:
C:\Windows\system32
C:\Program Files\Executables
C:\Documents and Settings\klint\My Documents\bin

nicely, one per line. My first attempt resulted in breaking up the string at BOTH the semicolons and the spaces. That's why I ended up with that for /f "delims=;" monstrosity above.

What I've come up with now is the following algorithm:
1. Replace all spaces with a "unique" string;
2. Iterate through semicolon-separated elements;
3. For each element, replace the "unique" string with a space.

Something like this (assumes the string '@#@' is not present in any variable I might ever want to look at):

set v=!%1!
for %%i in (%v: =@#@%) do (
set w=%%i
echo !w:@#@= !
)

But that looks like a kludge, and won't work if the variable (e.g. PATH) contains the substring "@#@".


Report Offensive Follow Up For Removal

Response Number 5
Name: Razor2.3
Date: November 10, 2007 at 09:44:25 Pacific
Subject: Batch programming question
Reply: (edit)

Gah, let CMD do the string parsing work for you. After all, batch files/command scripts have no real logic ability.

set _IN=%*
set _IN=%_IN:;=";"%
CALL :loop %_IN%
GOTO :eof

:loop
@ECHO %~1
SHIFT
IF NOT "%~1"=="" GOTO loop

NOTE: Whatever you pass needs to be in quotes.
EX: a.cmd "%path%"


Report Offensive Follow Up For Removal


Response Number 6
Name: klint
Date: November 11, 2007 at 04:16:38 Pacific
Subject: Batch programming question
Reply: (edit)

I like your idea, Razor. I shortened it to the following three lines, and gave it the same interface as the original (so you can run it by typing "showvar path").

It works very well, except when the variable itself contains quotes.

@echo off
setlocal enabledelayedexpansion
for %%i in ("!%1:;=";"!") do echo %%~i


Report Offensive Follow Up For Removal






Use following form to reply to current message:

   Name: From My Computing.Net Settings
 E-Mail: From My Computing.Net Settings

Subject: Batch programming question

Comments:

 


  Homepage URL (*): 
Homepage Title (*): 
         Image URL: 
 
Data Recovery Software