Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Simulating a SELECT CASE type of command?

14,202 views
Skip to first unread message

Robert Crandal

unread,
Mar 4, 2011, 9:15:44 PM3/4/11
to
My BAT file will likely contain a large quantity if "IF - GOTO"
lines. I was wondering, do BAT files have a simpler way to
test variables? I'm interested in something similar to
below:

SELECT CASE %myVariable%

CASE 1: echo "Blah"
EXIT SELECT
CASE 2: echo "Hello"
EXIT SELECT
CASE 3: echo "Bye"
EXIT SELECT

END SELECT

Is anyone aware if BAT files have commands similar to that??

Thanks!


foxidrive

unread,
Mar 4, 2011, 9:27:17 PM3/4/11
to

The code you can use depends entirely on what you wish to do. There are
tricks and techniques - but your question can't be answered with code
unless you pose a specific case.

Tell us what you want to do and you'll be surprised at the ingenuity
that people in this group will apply (btw alt.msdos.batch.nt is the
right group for Windows NT and later Windows operating systems).

--
Regards,
Mic

Robert Crandal

unread,
Mar 4, 2011, 10:28:22 PM3/4/11
to
>>>
>>> SELECT CASE %myVariable%
>>>
>>> CASE 1: echo "Blah"
>>> EXIT SELECT
>>> CASE 2: echo "Hello"
>>> EXIT SELECT
>>> CASE 3: echo "Bye"
>>> EXIT SELECT
>>>
>>> END SELECT
>>>
>>>
>> The code you can use depends entirely on what you wish to do. There are
>> tricks and techniques - but your question can't be answered with code
>> unless you pose a specific case.
>>
>> Tell us what you want to do and you'll be surprised at the ingenuity that
>> people in this group will apply (btw alt.msdos.batch.nt is the right
>> group for Windows NT and later Windows operating systems).
> >

The above scenario pretty much IS what I want to do. I will be testing
the value of "myVariable", which contains numeric strings between "01" and
"12",
which correspond to months of the year. So, ideally, I'm looking for
something
similar to:

SELECT CASE %myVariable%
CASE 1 : set var="January"
CASE 2: set var="February"
.....
CASE 12: set var="December"
END SELECT

I can do this with a bunch of IF-GOTO statments, but that seems like
overkill.
I was just hoping that BAT files had special commands like SELECT CASE that
I might not be aware of.

And, BTW, I am using BAT files that will be used on Windows XP machines
or above. And, thanks for the reference to "alt.msdos.batch.nt"

Robert Crandal

foxidrive

unread,
Mar 4, 2011, 10:47:29 PM3/4/11
to
On 5/03/2011 14:28, Robert Crandal wrote:
> The above scenario pretty much IS what I want to do. I will be testing
> the value of "myVariable", which contains numeric strings between "01"
> and "12",
> which correspond to months of the year. So, ideally, I'm looking for
> something
> similar to:
>
> SELECT CASE %myVariable%
> CASE 1 : set var="January"
> CASE 2: set var="February"
> .....
> CASE 12: set var="December"
> END SELECT
>
> I can do this with a bunch of IF-GOTO statments, but that seems like
> overkill.

This might be overkill. :)


@echo off
set var=12
for /f "tokens=1,2" %%a in (
'echo 01 Jan
^&echo 02 Feb
^&echo 03 Mar
^&echo 04 Apr
^&echo 05 May
^&echo 06 Jun
^&echo 07 Jul
^&echo 08 Aug
^&echo 09 Sep
^&echo 10 Oct
^&echo 11 Nov
^&echo 12 Dec'
) do if %var%==%%a set mon=%%b

echo %mon%
pause


--
Regards,
Mic

foxidrive

unread,
Mar 4, 2011, 10:59:24 PM3/4/11
to


Keeping the same kind of style, but being far slower because it uses an
external command, this has the benefit of being a little easier to read.

@echo off
set var=06
for %%a in (
"01 Jan "
"02 Feb "
"03 Mar "
"04 Apr "
"05 May "
"06 Jun "
"07 Jul "
"08 Aug "
"09 Sep "
"10 Oct "
"11 Nov "
"12 Dec "
) do (
for /f "tokens=2" %%b in ('echo %%a^|find "%var%"') do set mon=%%b
)

billious

unread,
Mar 5, 2011, 12:32:38 AM3/5/11
to

"Robert Crandal" <rcranz...@gmail.com> wrote in message
news:EZGdnZPhif1KMOzQ...@giganews.com...


This solution developed using XP
It may work for NT4/2K

----- batch begins -------
[1]@echo off
[2]setlocal
[3]set myvar=6
[4]for /f "tokens=1,2" %%i in (selcase.txt) do if %myvar%==%%i set var=%%j
[5]set var
------ batch ends --------

Lines start [number] - any lines not starting [number] have been wrapped and
should be rejoined. The [number] that starts the line should be removed

where the file SELCASE.TXT contains
----- datafile begins -------
1 January
2 February
3 March
4 April
5 May
6 June
7 July
8 August
9 September
10 October
11 November
12 December

----- datafile ends -------

Notes:
[2] : not actually required - automatically deletes user-variables altered
during run
The sequence of lines in the datafile is not relevant. You could also add

03 March

for instance, to avoid the situation where leading-zero-suppression is used


This more-complex solution on the same lines developed using XP
It may work for NT4/2K

----- batch begins -------
[1]@echo off
[2]setlocal
[3]set myvar=6
[4]:: demo 1 - selection from internal table
[5](set intable=)
[6](set var=)
[7]for /f "tokens=1,2" %%i in (%~f0) do (
[8]if defined intable if %myvar%==%%i set var=%%j
[9]if %%i==[datatable] set intable=Y
[10]if %%i==[endtable] (set intable=)
[11])
[12]echo demo1 result: %var%
[13]echo =================
[14]
[15]:: demo 2 - selection from multiple internal tables (delayedexpansion)
[16]setlocal enabledelayedexpansion
[17]for %%t in (anothertable datatable anothertable missingtable) do (
[18](set intable=)
[19](set var=)
[20]for /f "tokens=1,2" %%i in (%~f0) do (
[21]if defined intable if %myvar%==%%i set var=%%j
[22]if %%i==[%%t] set intable=Y
[23]if %%i==[endtable] (set intable=)
[24])
[25]echo demo2 result from %%t: !var!
[26])
[27]echo =================
[28]
[29]:: demo 3 - selection from multiple internal tables (without
delayedexpansion)
[30]setlocal disabledelayedexpansion
[31]for %%t in (datatable anothertable missingtable anothertable) do call
:sub %%t
[32]echo =================
[33]goto :eof
[34]
[35]:sub
[36](set intable=)
[37](set var=)
[38]for /f "tokens=1,2" %%i in (%~f0) do (
[39]if defined intable if %myvar%==%%i set var=%%j
[40]if %%i==[%1] set intable=Y
[41]if %%i==[endtable] (set intable=)
[42])
[43]echo demo3 result from %1: %var%
[44]goto :eof
[45][datatable]
[46]1 January
[47]2 February
[48]3 March
[49]4 April
[50]5 May
[51]6 June
[52]7 July
[53]8 August
[54]9 September
[55]10 October
[56]11 November
[57]12 December
[58]01 January
[59]02 February
[60]03 March
[61]04 April
[62]05 May
[63]06 June
[64]07 July
[65]08 August
[66]09 September
[67][endtable]
[68][anothertable]
[69]0 Black
[70]1 Brown
[71]2 Red
[72]3 Orange
[73]4 Yellow
[74]5 Green
[75]6 Blue
[76]7 Purple
[77]8 Grey
[78]9 White
[79][endtable]
------ batch ends --------


Notes:
The datatable(s) appeat within [tablename] [entable] brackets within the
batchfile
[5,6] this syntax ensures that the variable is deleted from the environment
as it is immune to stray trailing spaces
[7] ~f0 is evaluated to the full filename of the batch being run (see batch
documentation

FOR /?

for more details - especially if your path contains spaces...)

[25] Since VAR is changed WITHIN a FOR loop, we need to use the syntax !var!
to extract the RUN-TIME rather than the PARSE-TIME value. This necessitates
ENABLEDELAYEDEXPANSION mode invoked at [16]

[33,44] :EOF (WITH the colon) is defined as physical end-of-file. It does
not need to be (and indeed should not be) explicitly inserted.

Demo3 is simply another approach, using an internal subroutine. This avoids
DELAYEDEXPANSION and !var! but requires that the metavariable (%%t for the
outer loop) is supplied to the subroutine (here as the routine's first
parameter, accessed as %1.) Note that %%t and the batch file's parameters
are NOT available within the internal routine.

Personally, I'd use the first approach. It may use more files, but it means
that maintenance is easy should the table(s) need to be changed - you don't
have to find every batch containing an instance of your table...


AND, AAMOI if you want to involke a structure like

SELECT CASE %myVariable%

CASE 1: GOTO Label1
CASE 2: GOTO Label2
CASE 3: GOTO Label3

END SELECT

(or CALL Labelx) then this is easily accommodated.


Robert Crandal

unread,
Mar 5, 2011, 2:06:07 AM3/5/11
to
"foxidrive" <foxi...@gotcha.woohoo.invalid> wrote in message
news:tnicp.7706$8g3....@newsfe17.iad...

>
> This might be overkill. :)
>
> @echo off
> set var=12
> for /f "tokens=1,2" %%a in (
> 'echo 01 Jan
> ^&echo 02 Feb
> ^&echo 03 Mar
> ^&echo 04 Apr
> ^&echo 05 May
> ^&echo 06 Jun
> ^&echo 07 Jul
> ^&echo 08 Aug
> ^&echo 09 Sep
> ^&echo 10 Oct
> ^&echo 11 Nov
> ^&echo 12 Dec'
> ) do if %var%==%%a set mon=%%b
>
> echo %mon%
> pause
>

No, I dont think it's overkill because it worked just fine for me! 8)

I was just wondering, can you explain what is going on in the middle
with all those "^&echo 02 Feb" etc. commands?? It was my
(newbie) understanding that FOR /F is for iterating through files, but it
looks like you're not using files here? Just curious.

Robert Crandal

Robert Crandal

unread,
Mar 5, 2011, 2:23:00 AM3/5/11
to
billious, thanks thanks for the excellent solutions. I didn't know that
batch files had so many advanced commands! I'll play around
with the solutions that involve internal datatables, since I prefer to
solve this by using only one batch file. I'm always worried that
external data files can be lost, modified or deleted! 8(


"billious" <billio...@hotmail.com> wrote in message
news:zJydnZO9Kb5kV-zQ...@westnet.com.au...

Herbert Kleebauer

unread,
Mar 5, 2011, 3:00:30 AM3/5/11
to
Robert Crandal wrote:

> The above scenario pretty much IS what I want to do. I will be testing
> the value of "myVariable", which contains numeric strings between "01" and
> "12",
> which correspond to months of the year. So, ideally, I'm looking for
> something
> similar to:
>
> SELECT CASE %myVariable%
> CASE 1 : set var="January"
> CASE 2: set var="February"
> .....
> CASE 12: set var="December"
> END SELECT


@echo off

set m=4

set m[1]=Januar & set m[2]=Februar & set m[3]=Maerz & set m[4]=April
set m[5]=Mai & set m[6]=Juni & set m[7]=Juli & set m[8]=August
set m[9]=September&set m[10]=Oktober&set m[11]=November&set m[12]=Dezember

call set m=%%m[%m%]%%

echo %m%

foxidrive

unread,
Mar 5, 2011, 10:28:42 AM3/5/11
to

Any commands between the ' and ' that generates text is what the for in
do parses.

The above is merely a set of echo commands chained into one command
using the & separator as below.

echo 01 Jan&echo 02 Feb&echo 03 Mar&echo 04 Apr&echo 05 May&echo 06
Jun&echo 07 Jul&echo 08 Aug&echo 09 Sep&echo 10 Oct&echo 11 Nov&echo 12 Dec

So the for in do command parses the list as if it was from a simple
command such as 'dir /b ^|find /i ".exe"'


When used inside the ' and ' command tail then certain characters need
to be escaped with the ^ character, such as & > < | and which is why the
trailing echo commands have ^& preceeding them.

--
Regards,
Mic

Todd Vargo

unread,
Mar 5, 2011, 12:59:27 PM3/5/11
to

"foxidrive" <foxi...@gotcha.woohoo.invalid> wrote in message
news:yyicp.10325$1a1....@newsfe07.iad...

Or try this one. This will work, assuming no file exists in current folder
with a name that matches items in the list.

@echo off
set var=06
for %%a in (

01.January
02.February
03.March
04.April
05.May
06.June
07.July
08.August
09.September
10.October
11.November
12.December
) do (
if %%~na. equ %var%. set mon=%%~xa
)
set "mon=%mon:~1%"
echo %mon%
pause


--
Todd Vargo

(Post questions to group only. Remove "z" to email personal messages)

Todd Vargo

unread,
Mar 5, 2011, 1:16:15 PM3/5/11
to
Todd Vargo wrote:
>
> Or try this one. This will work, assuming no file exists in current folder
> with a name that matches items in the list.
>
> @echo off
> set var=06
> for %%a in (
> 01.January
> 02.February
> 03.March
> 04.April
> 05.May
> 06.June
> 07.July
> 08.August
> 09.September
> 10.October
> 11.November
> 12.December
> ) do (
> if %%~na. equ %var%. set mon=%%~xa
> )
> set "mon=%mon:~1%"
> echo %mon%
> pause

Actually, it does not matter if a file exists with a name found in the list,
it will not prevent this code from working correctly.

foxidrive

unread,
Mar 5, 2011, 1:19:02 PM3/5/11
to
On 6/03/2011 04:59, Todd Vargo wrote:
>
> "foxidrive" <foxi...@gotcha.woohoo.invalid> wrote in message
> news:yyicp.10325$1a1....@newsfe07.iad...
>> On 5/03/2011 14:47, foxidrive wrote:
>>> On 5/03/2011 14:28, Robert Crandal wrote:
>>>> The above scenario pretty much IS what I want to do. I will be testing
>>>> the value of "myVariable", which contains numeric strings between "01"
>>>> and "12",
>>>> which correspond to months of the year. So, ideally, I'm looking for
>>>> something
>>>> similar to:
>>>>
>>>> SELECT CASE %myVariable%
>>>> CASE 1 : set var="January"
>>>> CASE 2: set var="February"
>>>> .....
>>>> CASE 12: set var="December"
>>>> END SELECT
>>>>
>>>> I can do this with a bunch of IF-GOTO statments, but that seems like
>>>> overkill.

> Or try this one. This will work, assuming no file exists in current


> folder with a name that matches items in the list.
>
> @echo off
> set var=06
> for %%a in (
> 01.January
> 02.February
> 03.March
> 04.April
> 05.May
> 06.June
> 07.July
> 08.August
> 09.September
> 10.October
> 11.November
> 12.December
> ) do (
> if %%~na. equ %var%. set mon=%%~xa
> )
> set "mon=%mon:~1%"
> echo %mon%
> pause

Both yours and Herbert's are elegant, fast and easy to recognise the
block of code in the script.


Herbert's was a bit frugal with variable names so I expanded it a tad:


@echo off

set num=4

set m[1]=Januar
set m[2]=Februar
set m[3]=Maerz


set m[4]=April
set m[5]=Mai

set m[6]=Juni
set m[7]=Juli


set m[8]=August
set m[9]=September

set m[10]=Oktober
set m[11]=November
set m[12]=Dezember

call set mon=%%m[%num%]%%

Tom Lavedas

unread,
Mar 7, 2011, 10:53:10 AM3/7/11
to

While all of the responses are good and some are very ingenious
methods, I don't see any that come close to answering the original
question as it was asked originally. So, here is my two (three=)
cents.

IMHO, the closest structure inherent in batch to the Select/case of
most programming languages is probably the If () else() construct,
when done something like this ...

if %myVariable% equ 1 (
echo "Blah"
) else if %myVariable% equ 2 (
echo "Hello"
) else if %myVariable% equ 3 (
echo "Bye"
)

Then to expand on this to actually make it look like a Select/Case
(using the month example of the later posts) ...

@echo off
set month=
setlocal enabledelayedexpansion
set mon=%1
set "select=if x==y (rem "
set "case=) else if %mon% equ "
set "end=)"

%Select%
%case% 1 (
set Month=January
%case% 2 (
set Month=February
%case% 3 (
set Month=March
%case% 4 (
set Month=April
%case% 5 (
set Month=May
%case% 6 (
set Month=June
%case% 7 (
set Month=July
%case% 8 (
set Month=August
%case% 9 (
set Month=September
%case% 10 (
set Month=October
%case% 11 (
set Month=November
%case% 12 (
set Month=December
%end%

endlocal & set Month=%month%
echo Month %1 is %month%

I do acknowledge that for this example several of the other approaches
are probably more efficient (in code length, at least), but I was
compelled to offer my humble opinion ;-)

Finally, my contribution to selecting something from a list (not
really a select case, but) ...

@echo off
set month=
setlocal
set cases=January February March April May June July August
set cases=%cases% September October November December
set mon=%1
call :Select %mon% from %Cases%
endlocal & set Month=%result%
echo Month %1 is %month%
goto :EOF

:Select
for /l %%n in (1,1,%1) do shift
set result=%2
_____________________
Tom Lavedas

Klaus Meinhard

unread,
Mar 8, 2011, 5:08:35 PM3/8/11
to
Hallo Robert Crandal,

If you're really using DOS, go to my website and download 4DOS V8.00
If you're using NT/XP/Vista/Win7, goto www.JPSOFT.COM and download
TCC/LE. Both are command processors for their respective operating
systems, compatible with the included simple command processor, but
much more powerful. Best of all, both are free.

Both have Switch ... Case ... Default ... Endswitch commands, among
numerous other ways to write structured batch code. Install one of
them, hit F1 and start reading the help file. You'll never look back.


--
Best regards,

* Klaus Meinhard *
<www.4dos.info>


0 new messages