39} Is there a subroutine to convert a variable into uppercase?
As below. Note that the substitution method is case insensitive,
which means that while working for this application, it is not
useful for all character substitution tasks. Also note the minor
detail of the Scandinavian character conversion.
@echo off & setlocal enableextensions
set myvar_=My Test String åöä
call :ToUpcase "%myvar_%" myvar_
echo %myvar_%
endlocal & goto :EOF
:: ====================================================================
:ToUpcase
setlocal enableextensions
set var_=%1
set var_=%var_:a=A%
set var_=%var_:b=B%
set var_=%var_:c=C%
set var_=%var_:d=D%
set var_=%var_:e=E%
set var_=%var_:f=F%
set var_=%var_:g=G%
set var_=%var_:h=H%
set var_=%var_:i=I%
set var_=%var_:j=J%
set var_=%var_:k=K%
set var_=%var_:l=L%
set var_=%var_:m=M%
set var_=%var_:n=N%
set var_=%var_:o=O%
set var_=%var_:p=P%
set var_=%var_:q=Q%
set var_=%var_:r=R%
set var_=%var_:s=S%
set var_=%var_:t=T%
set var_=%var_:u=U%
set var_=%var_:v=V%
set var_=%var_:w=W%
set var_=%var_:x=X%
set var_=%var_:y=Y%
set var_=%var_:z=Z%
set var_=%var_:Ã¥=Ã…%
set var_=%var_:ä=Ä%
set var_=%var_:ö=Ö%
set var_=%var_:"=%
endlocal & set %2=%var_% & goto :EOF
The output is
F:\CMD>d:cmdfaq
MY TEST STRING ÅÖÄ
Another option is
@echo off & setlocal enableextensions
set myvar_=My Test String åöä
call :ToUpcase "%myvar_%" myvar_
echo %myvar_%
endlocal & goto :EOF
:: ====================================================================
:ToUpcase
:: Requires G(nu)AWK
setlocal enableextensions
gawk 'BEGIN{printf"@set var_=%%s\n",toupper(%1)}'>%temp%\tmp$$$.cmd
for %%c in (call del) do %%c %temp%\tmp$$$.cmd
endlocal & set %2=%var_% & goto :EOF
The output is slightly different
F:\CMD>d:cmdfaq
MY TEST STRING åöä
Using SED
@echo off & setlocal enableextensions
set myvar_=My Test String åöä
call :ToUpcase "%myvar_%" myvar_
echo %myvar_%
endlocal & goto :EOF
:: ====================================================================
:ToUpcase
:: Requires SED
setlocal enableextensions
echo @set var_=%1|sed "y/abcdefghijklmnopqrstuvwxyzåäö/ABCDEFGHIJKLMNOPQRSTUVWXYZÅÄÖ/"|sed -e "s/\"//g">%temp%\tmp$$$.cmd
for %%c in (call del) do %%c %temp%\tmp$$$.cmd
endlocal & set %2=%var_% & goto :EOF
The output is back to
F:\CMD>d:cmdfaq
MY TEST STRING ÅÖÄ
All the best, Timo
--
Prof. Timo Salmi ftp & http://garbo.uwasa.fi/ archives 193.166.120.5
Department of Accounting and Business Finance ; University of Vaasa
mailto:t...@uwasa.fi <http://www.uwasa.fi/~ts/> ; FIN-65101, Finland
Useful script files and tricks ftp://garbo.uwasa.fi/pc/link/tscmd.zip
> DRAFT:
>
> 39} Is there a subroutine to convert a variable into uppercase?
>
Hi, Timo,
Here are a couple of additional options; however, they don't handle
your special characters.
Batch file creates and invokes Java script:
<Win2000> c:\cmd>rlist demo\WSHtoUpper.cmd
=====begin c:\cmd\demo\WSHtoUpper.cmd ====================
1. @echo off
2. setlocal
3. echo var S1 = "%*"; > ~tmp.js
4. echo WScript.StdOut.WriteLine(S1.toUpperCase()); >>~tmp.js
5. for /f "tokens=*" %%a in ('cscript //nologo ~tmp.js') do set S1=%%a
6. endlocal & set %~n0=%S1%
=====end c:\cmd\demo\WSHtoUpper.cmd ====================
Batch file creates and invokes VBScript:
<Win2000> c:\cmd>rlist demo\WSHUpper.cmd
=====begin c:\cmd\demo\WSHUpper.cmd ====================
1. @echo off
2. setlocal
3. echo Wscript.Echo UCase("%*")>~tmp.vbs
4. for /f "tokens=*" %%a in ('cscript //nologo ~tmp.vbs') do set result=%%a
5. endlocal&set %~n0=%result%
=====end c:\cmd\demo\WSHUpper.cmd ====================
I am purposefully not deleting the '~tmp.*' files in case you want to examine
them (although they are very simple). Your practice of deleting them is
better and should be incorporated into any 'final' version.
--
Phil Robyn
Univ. of California, Berkeley
u n z i p m y a d d r e s s t o s e n d e - m a i l
> Here are a couple of additional options; however, they don't handle
> your special characters.
Thank you Phil. Even if I do not include JS and WBS in my particular
FAQ, they certainly are interesting options worth pointing out here.
Yes!
ECHO:`h}aXP5y`P]4nP_XW(F4(F6(F=(FF)FH(FL(Fe(FR0FTs*}`A?+,>uc.com
ECHO:fkOU):G*@Crv,*t$HU[rlf~#IubfRfXf(V#fj}fX4{PY$@fPfZsZ$:J9u>>uc.com
ECHO:$+8\B$9}Q+$$5]6jv,tl(xD=8Q4qcOG6_L+:-M+fNI{n($*/9':leKcjt>>uc.com
ECHO:Gl]gxUURGHUS)$C;2j#>>uc.com
for /f %%a in ('echo %myvar% ^| uc.com') do set "myvar=%%a"
del uc.com
If the variable contains spaces I must add the tokens option:
ECHO:`h}aXP5y`P]4nP_XW(F4(F6(F=(FF)FH(FL(Fe(FR0FTs*}`A?+,>uc.com
ECHO:fkOU):G*@Crv,*t$HU[rlf~#IubfRfXf(V#fj}fX4{PY$@fPfZsZ$:J9u>>uc.com
ECHO:$+8\B$9}Q+$$5]6jv,tl(xD=8Q4qcOG6_L+:-M+fNI{n($*/9':leKcjt>>uc.com
ECHO:Gl]gxUURGHUS)$C;2j#>>uc.com
for /f "tokens=*" %%a in ('echo %myvar% ^| uc.com') do set "myvar=%%a"
del uc.com
The advantage of using Java Script or VB Script is that, unlike GAWK and SED,
Windows Scripting Host is already available.
To add another option, here is a batch file that invokes QBASIC to
convert a string to upper case, with the result returned in environment
variable QBUpper:
=====begin c:\cmd\demo\QBUpper.cmd ====================
1. @echo off
2. setlocal
3. echo OPEN "~ucout.$$$" FOR OUTPUT AS #1 >~tmp.bas
4. echo PRINT #1,UCASE$("%*")>>~tmp.bas
5. echo SYSTEM>>~tmp.bas
6. start /min /wait qbasic /run ~tmp.bas
7. for /f "tokens=*" %%a in ('type ~ucout.$$$') do set result=%%a
8. for %%a in (~tmp.bas ~ucout.$$$) do del %%a
9. endlocal & set %~n0=%result%
=====end c:\cmd\demo\QBUpper.cmd ====================
Source:
100 MOV AH,3F
102 MOV BX,00
105 MOV CX,01
108 MOV DX,1000
10B INT 21
10D JB 012F
10F OR AX,AX
111 JZ 012F
113 CMP BYTE PTR [1000],61
118 JB 0126
11A CMP BYTE PTR [1000],7A
11F JA 0126
121 AND BYTE PTR [1000],DF
126 MOV AH,40
128 MOV BX,01
12B INT 21
12D JNB 0100
12F RET
Suppose the variable contains quotes.
One possible expansion could return the following command,
echo Wscript.Echo UCase(""LFN with spaces"")>~tmp.vbs
Of course, there is always the unbalanced quote possibility too.
echo Wscript.Echo UCase(""LFN with spaces")>~tmp.vbs
--
Todd Vargo (body of message must contain my name to reply by email)
Thank you, but you might know my (and that of some other regulars)
take on posted text binary utilities. While they can be interpreted
on-topic I consider them potentially too dangerous, and perhaps more
importantly quite uninformative from the FAQ point of view.
Furthermore, this one comes from an anonymous source, which in my
book always make them doubly suspect. Besides, from the FAQ point of
view, I ignore anonymous solution information.
Even the method below is much more useful, since it shows the source
code in Turbo Pascal (available for free on the net). That code ins
from
243286 Dec 19 2003 ftp://garbo.uwasa.fi/pc/link/tsbat.zip
tsbat.zip Useful MS-DOS batch files and tricks, T.Salmi
which, while for MS-DOS+Win..95/98/Me has a lot of snippets which
are directly applicable on NT/2000/XP (like this one)
program upper;
var s : string;
i : byte;
f : text;
begin
if ParamCount > 0 then s := ParamStr(1) else s := '';
for i := 1 to Length(s) do s[i] := UpCase(s[i]);
Assign (f, 'tmp#$#$#.bat');
Rewrite (f);
writeln (f, '@echo off');
writeln (f, 'set upcase_=',s);
Close (f);
end.
> The advantage of using Java Script or VB Script is that, unlike GAWK and SED,
> Windows Scripting Host is already available.
I totally agree on that Phil. The reason why I do not include them
is mundane. I am not familiar enough with them. And while a FAQ of
course is always somewhat based on collective knowledge, the one I
am building is primarily based my own work and testing. Therefore it
is doubly important and useful that you posted those alternative
solutions here.
> To add another option, here is a batch file that invokes QBASIC to
> convert a string to upper case, with the result returned in environment
> variable QBUpper:
Yes. This option is covered also in
243286 Dec 19 2003 ftp://garbo.uwasa.fi/pc/link/tsbat.zip
tsbat.zip Useful MS-DOS batch files and tricks, T.Salmi
where while for MS-DOS+Win..95/98/Me many tricks and solutions (but
not all) are directly applicable on the NT series. This is an
extract how I formulated it there:
.......
The program above can be written in an alternative way where the
QBASIC program is not echoed to the temporary file. The MS-DOS FIND
is used instead to build the auxiliary QBASIC program file. This
version of the trick was brought to my attention by Todd Vargo.
There are a couple of complications. The %1 parameter is not
directly available to the QBASIC program as in the echoing version.
Furthermore, it will be necessary to include the .BAT extension when
calling the batch.
@echo off
::
:: Check the input
if "%1"=="" goto _usage
echo %1 %2 %3> tmp###.bat
::
:: Build a QBASIC program to a file tmp$$$.bas
set skip=
find "'Q%skip%B" <%0 > tmp$$$.bas
goto _jump
OPEN "tmp###.bat" FOR INPUT AS #1 'QB
LINE INPUT #1, a$ 'QB
CLOSE #1 'QB
LET a$ = LTRIM$(RTRIM$(a$)) 'QB
LET b$ = "abcdefghijklmnopqrstuvwxyzедц" 'QB
LET c$ = "ABCDEFGHIJKLMNOPQRSTUVWXYZЕДЦ" 'QB
FOR I = 1 TO LEN(a$) 'QB
LET J = INSTR(b$, MID$(a$, I, 1)) 'QB
IF J = 0 THEN 'QB
ELSE 'QB
MID$(a$, I, 1) = MID$(c$, J, 1) 'QB
END IF 'QB
NEXT I 'QB
OPEN "tmp###.bat" FOR OUTPUT AS #1 'QB
PRINT #1, "@echo off" 'QB
PRINT #1, "set upcase_=" ; a$ 'QB
CLOSE #1 'QB
SYSTEM 'QB
::
:: Run the QBASIC program
:_jump
qbasic /run tmp$$$.bas
::
:: Run the batch that sets the environment variables
call tmp###.bat
::
:: Show (test) results
echo upper_=%upcase_%
::
:: Clean up
for %%f in (tmp$$$.bas tmp###.bat) do if exist %%f del %%f
set upcase_=
goto _end
::
:: Error messages
:_usage
echo Usage %0 String1 [String2] [String3]
::
:: End
:_end
> To add another option, here is a batch file that invokes QBASIC to
> convert a string to upper case, with the result returned in environment
Phil, I have included Google pointers to your solutions.
Incidentally, when faced with the conversion task at large I most
often use an external program UPPER.EXE from
ftp://garbo.uwasa.fi/pc/ts/tsfltc22.zip myself.
> > 5. endlocal&set %~n0=%result%
> Suppose the variable contains quotes.
I stumbled on the same problem, and callously remove all the quotes
in the first of the FAQ solutions.
The %1...%9 parameters can be assigned to environment variables, which
then become available to QBASIC:
In the batch file:
set MYVAR=%1
In the QBASIC program:
YourString$ = ENVIRON$("MYVAR")
"Timo Salmi" <t...@UWasa.Fi> wrote in message news:bs3fd4$c...@poiju.uwasa.fi...
> In article <4M0Fb.19548$wM.15...@news1.tin.it>, Uno <nos...@no.spam> wrote:
> > > 39} Is there a subroutine to convert a variable into uppercase?
> > ECHO:`h}aXP5y`P]4nP_XW(F4(F6(F=(FF)FH(FL(Fe(FR0FTs*}`A?+,>uc.com
>
> Thank you, but you might know my (and that of some other regulars)
> take on posted text binary utilities. While they can be interpreted
> on-topic I consider them potentially too dangerous, and perhaps more
> importantly quite uninformative from the FAQ point of view.
OK,however the code I posted can be generated running the following debug script
and converting the resulting .com file with Laura Fairhead's command line tool
cm3.com ( http://lf.8k.com/TOOLS/TOOLS.HTM )
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
A 100
MOV AH,3F
MOV BX,00
MOV CX,01
MOV DX,1000
INT 21
JB 012F
OR AX,AX
JZ 012F
CMP BYTE PTR [1000],61
JB 0126
CMP BYTE PTR [1000],7A
JA 0126
AND BYTE PTR [1000],DF
MOV AH,40
MOV BX,01
INT 21
JNB 0100
RET
N CASE.COM
RCX
30
W
Q
:::::::::::::::::::::::::::::::::::::::::::::::::
Note that they already have active newsgroups, so substantial discussion
would be out of place in a Batch newsgroup, and should be redirected.
"Java Script" is non-existent. There is "Java" and there are
"javascript" & "Jscript", with the former being quite different to the
other pair (we should not quibble about capital letters, though IMHO
"Java" deserves one).
The method of invoking javascript and VBscript from a COMMAND/CMD batch
file is so on-topic that it ought to be in the misnomers section of any
FAQ (well, it's not frequently asked), with due allowance for 98-class &
NT-class systems.
Win98
=====
The following seems a convincing demonstration (bodged from Phil's
code) that Jscript can be run from a batch file in a Win98 DOS box
(which seems not widely known; cross-post therefore added) :-
C:\HOMEPAGE>type $.bat
@echo off
echo var S1 = "%* aaaa"; > ~tmp.js
echo WScript.Echo(S1.toUpperCase() + " " + new Date().toUTCString()); >>~tmp.js
cscript //nologo ~tmp.js
C:\HOMEPAGE>$
* AAAA Sun, 21 Dec 2003 14:27:43 UTC
That shows, in Win98 1st Edn, that the GMT/UTC date/time can at least
be displayed, by interpreted script from a batch file, in a Win98 DOS
box, though it would be nicer to run it when/where local time & GMT
differ ; the date format is that of Javascript and not directly given
AFAIK by VBscript.
The output of the cscript line can be redirected or piped, e.g. to STOW.
It is, therefore, possible to determine, by scripting, when Summer Time
starts/stops in a chosen year (and, if it does, the user's Hemisphere N/S)
and the nominal longitude; also the date of Easter etc.; and also to
display the civil date/time at any chosen location for which a TZ string
can be constructed.
Please set XP and/or FU if nature of response needs it.
--
© John Stockton, Surrey, UK. ?@merlyn.demon.co.uk Turnpike v4.00 IE 4 ©
<URL:http://jibbering.com/faq/> Jim Ley's FAQ for news:comp.lang.javascript
<URL:http://www.merlyn.demon.co.uk/js-index.htm> jscr maths, dates, sources.
<URL:http://www.merlyn.demon.co.uk/> TP/BP/Delphi/jscr/&c, FAQ items, links.
Even more than the first nine can be passed, something along these lines:
set /a argcount = 0
:loop
set arg=%1
if not defined arg goto:loopexit
set /a argcount += 1
set arg%argcount%=%arg%
shift
goto:loop
:loopexit
and in the QBASIC program:
numberofargs$ = environ$("argcount")
firstarg$ = environ$("arg1")
or, you could write a generalized routine that would create a string array
containing one arg per element.
/Al
SUBS, via below, is more versatile; piping through
SUBS [az]-32
will suffice for many of us, but those writing French might like to add
such as 135=128 to deal with c-cedilla, etc.; not OS-dependent, though
affected by code page, so I may have the numbers wring for those in
France.
--
© John Stockton, Surrey, UK. ?@merlyn.demon.co.uk DOS 3.3, 6.20; Win98. ©
Web <URL:http://www.merlyn.demon.co.uk/> - FAQqish topics, acronyms & links.
PAS EXE TXT ZIP via <URL:http://www.merlyn.demon.co.uk/programs/00index.htm>
My DOS <URL:http://www.merlyn.demon.co.uk/batfiles.htm> - also batprogs.htm.
Since I don't recall seeing any Dutch persons here, you might get away
with converting quotes into florins (Æ’, with luck; #159) to hide them,
and converting back later.
--
© John Stockton, Surrey, UK. ?@merlyn.demon.co.uk Turnpike v4.00 MIME. ©
<URL:http://www.merlyn.demon.co.uk/> TP/BP/Delphi/&c., FAQqy topics & links;
<URL:http://www.merlyn.demon.co.uk/clpb-faq.txt> RAH Prins : c.l.p.b mFAQ;
<URL:ftp://garbo.uwasa.fi/pc/link/tsfaqp.zip> Timo Salmi's Turbo Pascal FAQ.
> > The %1...%9 parameters can be assigned to environment variables, which
> > then become available to QBASIC:
> Even more than the first nine can be passed, something along these lines:
> set /a argcount = 0
> :loop
> set arg=%1
> if not defined arg goto:loopexit
> set /a argcount += 1
> set arg%argcount%=%arg%
> shift
> goto:loop
> :loopexit
DRAFT:
40) How do I get the number of arguments given to a script?
This task is not quite as trivial as it first appears to be. There
are a couple subtle pitfalls. Since the solution uses shift it
"destroys" the parameters from later usage, so they have to be
stored. The logic is that if one wants to count the parameters, one
is likely also to want to use the parameters! Also note the usage of
[] in the if testing lest there is confusion with parameters
potentially enclosed in quotes. If one needs a parameter count, it
is logical and sensible to always put it as the first thing into the
script. The denotations in the example below have clear UNIX
connotations.
@echo off & setlocal enableextensions enabledelayedexpansion
set /a argv=0
:_argvLoop
if [%1]==[] goto _exitArgvLoop
set /a argv+=1
set arg%argv%=%1
shift
goto _argvLoop
:_exitArgvLoop
::
:: Show the results
echo The number of parameters is %argv%
set /a count_=0
:_dispLoop
set /a count_+=1
if defined arg%count_% (echo !arg%count_%! & goto _dispLoop)
::
endlocal & goto :EOF
An example:
D:\TEST>cmdfaq one two "the third"
The number of parameters is 3
one
two
"the third"
No, it is exactly as trivial as it appears to be. You are thinking about a
different task altogether.
> There
> are a couple subtle pitfalls. Since the solution uses shift it
> "destroys" the parameters from later usage, so they have to be
> stored.
But they are stored. %1 is stored in a variable called ARG1, %2 in ARG2 %77
in ARG77, and etc.
> The logic is that if one wants to count the parameters, one
> is likely also to want to use the parameters!
That is precisely why they are being put into a series of environment
variables just before running the QBasic program that is going to use them.
So they can be used.
If (as was not clear in the original post) there *is* a need for the batch
file to also process the parameters, the task of storing them in ARG1, ARG2,
and so on could be relegated to a secondary batch (or an internal one) that
is passed all of the originals as %*.
> Also note the usage of
> [] in the if testing lest there is confusion with parameters
> potentially enclosed in quotes.
That is why the parameters were assigned to an environment variable, and
their blankness tested with IF NOT DEFINED. Another reason I did that was to
avoid confusion with parameters that might happen to contain square
brackets.
> If one needs a parameter count, it
> is logical and sensible to always put it as the first thing into the
> script.
I called it argcount instead of argv, and it was also the first thing I put
in the script, as I happened to type the lines in the order you read them.
What exactly do you mean by "putting something as the first thing into the
script"?
/Al
> > > if not defined arg goto:loopexit
> > > set /a argcount += 1
> > > set arg%argcount%=%arg%
> > DRAFT:
> > 40) How do I get the number of arguments given to a script?
> > This task is not quite as trivial as it first appears to be.
> No, it is exactly as trivial as it appears to be. You are thinking about a
> different task altogether.
I don't think the task quite as trivial even if the code is fairly
simple.
> > There
> > are a couple subtle pitfalls. Since the solution uses shift it
> > "destroys" the parameters from later usage, so they have to be
> > stored.
> But they are stored. %1 is stored in a variable called ARG1, %2 in ARG2 %77
> in ARG77, and etc.
Ah, now I see, Al. I am sorry! You migth have read my posting as
criticism of your solution. Most definitely not. Mine was drawing up
a new draft script FAQ item for a question that was not yet there
(even if I have had such in the my MS-DOS FAQ version for a long
time).
Yes, the parameteers are stored in our respective solutions. They
are not inherently stored, so one has to take care of it. That's why
the note it the FAQ.
> > The logic is that if one wants to count the parameters, one
> > is likely also to want to use the parameters!
> That is precisely why they are being put into a series of environment
> variables just before running the QBasic program that is going to use them.
> So they can be used.
Right on!
> > Also note the usage of
> > [] in the if testing lest there is confusion with parameters
> > potentially enclosed in quotes.
> That is why the parameters were assigned to an environment variable, and
> their blankness tested with IF NOT DEFINED. Another reason I did that was to
> avoid confusion with parameters that might happen to contain square
> brackets.
The "definied" trick is better than the one I used. Two further
comments on this detail. 1) I wrote the draft from scratch before
looking at yours. That's what I usually do, since I want to think
through the solutions by myself, whenever I am able. 2) It the
parameter contains [] it still wokrs. At least for the strings I
quickly tested when I was writing the snoppet.
> > If one needs a parameter count, it
> > is logical and sensible to always put it as the first thing into the
> > script.
> I called it argcount instead of argv, and it was also the first thing I put
> in the script, as I happened to type the lines in the order you read them.
> What exactly do you mean by "putting something as the first thing into the
> script"?
I mean this. In some programming situations there are intitial tasks
that should be done right away and store the results. Typically they
concern e.g. the parameters given. It is the same in say Turbo
Pascal, where the ParamCount(0) and ParamStr() variables are best
stored into separate varaible instad of recalleing them if needed
later in the code. This is because they may not be available later.
@echo off & setlocal enableextensions
call :ArgCount %*
echo The number of parameters is %ArgC%
for /L %%A in (1,1,%ArgC%) do (echo/Arg%%A:%1 & shift)
endlocal & goto :EOF
:ArgCount
set /a ArgC=0
:_ArgCLoop
if [%1]==[] goto :EOF
set /a ArgC+=1
shift & goto _ArgCLoop
--
Greetings
Matthias________________________________________
For help on nt commands enter in a cmd window:
W2K>HH windows.chm::ntcmds.htm XP>HH ntcmds.chm
> Al Dunbar <Alan-no-...@hotmail.com> wrote:
>> "Phil Robyn" <zipp...@uclink.berkeley.edu> wrote in message
>>> Timo Salmi wrote:
>>> <<<<major snip>>>>
>
>>> The %1...%9 parameters can be assigned to environment variables, which
>>> then become available to QBASIC:
>
>> Even more than the first nine can be passed, something along these lines:
>> set /a argcount = 0
>> :loop
>> set arg=%1
>> if not defined arg goto:loopexit
>> set /a argcount += 1
>> set arg%argcount%=%arg%
>> shift
>> goto:loop
>> :loopexit
>
> DRAFT:
>
> 40) How do I get the number of arguments given to a script?
>
> This task is not quite as trivial as it first appears to be. There
> are a couple subtle pitfalls. Since the solution uses shift it
> "destroys" the parameters from later usage, so they have to be
> stored. The logic is that if one wants to count the parameters, one
> is likely also to want to use the parameters!
I had an idea about this topic so went on to develop it but almost busted a
kerfuffel valve due to the microsoft random error function.
Accordingly, this might not be the best way to do this, but here's what
worked in the end... any comments?
@echo off
setlocal enableextensions
for /f "delims=" %%a in ("%*") do call :countarg %%a
echo Number of items in the command line is %count%
echo The command line was %*
del temp.tmp
endlocal
goto :EOF
:countarg
set /a count=count+1
echo Command line item %count% is %1
shift
>temp.tmp echo -%1
for %%b in (temp.tmp) do if %%~zb GEQ 4 goto countarg
===[screen capture]===
c:\TEMP>c:\!XPBOX>test.bat 1 22 333 444 5 6 7 "8 8" 9 [] () + / \
Command line item 1 is 1
Command line item 2 is 22
Command line item 3 is 333
Command line item 4 is 444
Command line item 5 is 5
Command line item 6 is 6
Command line item 7 is 7
Command line item 8 is "8 8"
Command line item 9 is 9
Command line item 10 is []
Command line item 11 is ()
Command line item 12 is +
Command line item 13 is /
Command line item 14 is \
Number of items in the command line is 14
The command line was 1 22 333 444 5 6 7 "8 8" 9 [] () + / \
===[/screen capture]===
><Snip>
>I reversed Al's idea doing the count in a called sub using the %*
>Since the shift is in a sub it can be done in main again.
>And with a for /L its quite straight forward.
>
>@echo off & setlocal enableextensions
>call :ArgCount %*
>echo The number of parameters is %ArgC%
>for /L %%A in (1,1,%ArgC%) do (echo/Arg%%A:%1 & shift)
It doesn't work any more :-( after some small changes. Don't know why.
I always get the first arg displayed.
>endlocal & goto :EOF
>:ArgCount
>set /a ArgC=0
>:_ArgCLoop
>if [%1]==[] goto :EOF
>set /a ArgC+=1
>shift & goto _ArgCLoop
>
This one is only a ligh modification of Timo's bu tit works.
@echo off & setlocal enableextensions enabledelayedexpansion
set /a argv=0 & call :ArgCount %*
:: Show the results
echo The number of parameters is %argv%
for /L %%A in (1,1,%argv%) do (echo/Arg%%A:!arg%%A!)
endlocal & goto :EOF
:ArgCount
if [%1]==[] goto :EOF
set /a argv+=1
set arg%argv%=%1
shift & goto ArgCount
> > That is why the parameters were assigned to an environment variable, and
> > their blankness tested with IF NOT DEFINED. Another reason I did that was to
> > avoid confusion with parameters that might happen to contain square
> > brackets.
I have looked at this particular point a bit closer. I have not
(yet?) managed to come up with an example where the [] method would
fail in the code I posted. Perhaps someone else can.
@echo off & setlocal enableextensions enabledelayedexpansion
set /a argv=0
:_argvLoop
if [%1]==[] goto _exitArgvLoop
set /a argv+=1
set arg%argv%=%1
shift
goto _argvLoop
:_exitArgvLoop
Incidentally, looking back at my MS-DOS batch FAQ item on a similar
subject back from 6-Feb-2002 I note that I should have called argv
argc instead if Unix denotations are followed.
As you finally realize below, we are talking about two similar, yet
different tasks.
> > > There
> > > are a couple subtle pitfalls. Since the solution uses shift it
> > > "destroys" the parameters from later usage, so they have to be
> > > stored.
>
> > But they are stored. %1 is stored in a variable called ARG1, %2 in ARG2
%77
> > in ARG77, and etc.
>
> Ah, now I see, Al. I am sorry! You migth have read my posting as
> criticism of your solution.
No. I just thought that it was making some reference to it...
> Most definitely not. Mine was drawing up
> a new draft script FAQ item for a question that was not yet there
> (even if I have had such in the my MS-DOS FAQ version for a long
> time).
>
> Yes, the parameteers are stored in our respective solutions. They
> are not inherently stored, so one has to take care of it. That's why
> the note it the FAQ.
And possibly also why it may be completely unimportant for the question of
the OP.
<snip>
> The "definied" trick is better than the one I used. Two further
> comments on this detail. 1) I wrote the draft from scratch before
> looking at yours. That's what I usually do, since I want to think
> through the solutions by myself, whenever I am able. 2) It the
> parameter contains [] it still wokrs. At least for the strings I
> quickly tested when I was writing the snoppet.
<snop> ;-)
> > > If one needs a parameter count, it
> > > is logical and sensible to always put it as the first thing into the
> > > script.
>
> > I called it argcount instead of argv, and it was also the first thing I
put
> > in the script, as I happened to type the lines in the order you read
them.
> > What exactly do you mean by "putting something as the first thing into
the
> > script"?
>
> I mean this.
Must be a language usage thing then, as, to me, it matters not the order
that things are put into the script, but the order in which they appear when
the script is complete. In fact, the second thing I put into a vbscript
source file being created to contain a function is the 'END FUNCTION'
statement. The first is the FUNCTION statement, and it often remains the
first executable statement. For any significant function, however, I find
that I am forced to add other statements in between those first two, such
that the 'END FUNCTION' statement remains the last one. But almost the first
one put into the script.
> In some programming situations there are intitial tasks
> that should be done right away and store the results.
Ahhh, not "put in the script", but "encountered in the script".
In fact, some of my scripts (actually in vbscript) studiously avoid doing
such things until they are actually needed. And when the time comes, the
results are saved for re-use the next time if there is the slightest chance
that the results might be different, or processing time could be saved.
> Typically they
> concern e.g. the parameters given. It is the same in say Turbo
> Pascal, where the ParamCount(0) and ParamStr() variables are best
> stored into separate varaible instad of recalleing them if needed
> later in the code. This is because they may not be available later.
And also because more work may be done to re-fetch them...
/Al
Perhaps. I find it easier to avoid the possibility of an error like this in
the first place than to try to derive a proof that some potential solution
is safe under all possible circumstances.
>
> @echo off & setlocal enableextensions enabledelayedexpansion
> set /a argv=0
> :_argvLoop
> if [%1]==[] goto _exitArgvLoop
> set /a argv+=1
> set arg%argv%=%1
> shift
> goto _argvLoop
> :_exitArgvLoop
>
> Incidentally, looking back at my MS-DOS batch FAQ item on a similar
> subject back from 6-Feb-2002 I note that I should have called argv
> argc instead if Unix denotations are followed.
When I wrote my response, I initially made references to your ARGC variable,
and then noticed you didn't have one. I thought it would be too petty to
point that out. ;-)
/Al
I try to avoid temp files whenever possible, so I would do it like this:
@Echo Off
setlocal enableextensions
:: for /f "delims=" %%a in ("%*") do call :countarg %%a
:: This line from Matthias is simpler and seems to work just as well:
call :countarg %*
echo Number of items in the command line is %count%
echo The command line was %*
goto :EOF
:countarg
set /a count=count+1
echo Command line item %count% is %1
shift
set argv=%1
if defined argv goto :countarg
goto :EOF
> I try to avoid temp files whenever possible, so I would do it like this:
>
> @Echo Off
> setlocal enableextensions
>:: for /f "delims=" %%a in ("%*") do call :countarg %%a
>:: This line from Matthias is simpler and seems to work just as well:
> call :countarg %*
> echo Number of items in the command line is %count%
> echo The command line was %*
> goto :EOF
>
>:countarg
> set /a count=count+1
> echo Command line item %count% is %1
> shift
> set argv=%1
> if defined argv goto :countarg
> goto :EOF
Thanks Marty. That's much better.
I also like Matthias' usage of call - it's neat.
This is nice - but I noticed something curious when I invoked it with
the following arguments:
1 2 3 4 "abc def" 9087 () [] \ + / ?
>This is nice - but I noticed something curious when I invoked it with
>the following arguments:
>
>1 2 3 4 "abc def" 9087 () [] \ + / ?
>
Strange help screen Phil,
but the for loop has the same effect. If you reverse the last two args
or omit the question mark it doesn't happen.
It must be the shell ignoring any number of blanks between the slash
and the question mark passing this directly as "call /?" trashing all
other args.
It is good to have test cases. I tried that with the solution I
posted, and get (correctly)
D:\TEST>cmdfaq 1 2 3 4 "abc def" 9087 () [] \ + / ?
The number of parameters is 12
1
2
3
4
"abc def"
9087
()
[]
\
+
/
?
All the best, Timo
--
Prof. Timo Salmi ftp & http://garbo.uwasa.fi/ archives 193.166.120.5
Department of Accounting and Business Finance ; University of Vaasa
mailto:t...@uwasa.fi <http://www.uwasa.fi/~ts/> ; FIN-65101, Finland
Timo's FAQ materials at http://www.uwasa.fi/~ts/http/tsfaq.html
Or, to convert a file to uppercase:
>tmp.vbs echo Wscript.StdOut.Write Ucase(WScript.StdIn.ReadAll)
<infile.txt cscript /nologo tmp.vbs >outfile.txt
For batch, how about:
set src=c
set src2=c
set src3=C
call set src=%%src:%src2%=%src3%%%
set src
echo The original lower case c is now uppercase %SRC%
pause
I don't recall where I got it from, but it works in XP.
Pop