Command line parameter parsing issue

Discussion forum for all Windows batch related topics.

Moderator: DosItHelp

Post Reply
Message
Author
carlsomo
Posts: 91
Joined: 02 Oct 2012 17:21

Command line parameter parsing issue

#1 Post by carlsomo » 18 Nov 2012 23:29

:Message.bat
@echo off&setlocal
::Examine methods to determine if first arg is a quoted string
::or a single unquoted 'word'
call :version%~2 %1
goto :EOF

:version
echo please enter 1st arg as quoted if spaces else unquoted if not
echo second arg is '1' or '2' for version 1 or 2 of parameter handling
echo In Win7 a quoted string in Arg1 produces an error message in version 1
echo however version 2 seems to work. I am a bit perplexed.
goto :EOF

:Version1
echo(Version1
set "msg=%~1"
if %msg% equ %1 (echo %1... is not quoted) else (
echo %1... is quoted
)
goto :EOF

:Version2
echo(Version2
set "msg=%~1"
if %1 equ %msg% (echo %1... is not quoted) else (
echo %1... is quoted
)
goto :EOF

foxidrive
Expert
Posts: 6031
Joined: 10 Feb 2012 02:20

Re: Command line parameter parsing issue

#2 Post by foxidrive » 18 Nov 2012 23:52

If there are poison characters and spaces in %1 then %msg% will give you an error.

carlsomo
Posts: 91
Joined: 02 Oct 2012 17:21

Re: Command line parameter parsing issue

#3 Post by carlsomo » 19 Nov 2012 00:31

There does not seem to be an issue with poison characters in fact I have not even experimented with them on this simple routine. I have a batch that accepts user input and arg1 one and two are a "string" and variable submitted in either order. I went nuts trying to determine which was which and it was not until I put 'if %1 equ %msg%' rather than 'if %msg% equ %1' that it worked. I also determined that surrounding the if statement parameters with quotes or using carets^ in various places was doomed to failure. I was using the string, "Enter a string" and I would see the batch bomb out with the message 'a was unexpected at this time' or some such nonsense. I finally realized the 'a' was not somewhere in my code but the middle word I passed in my test parameter. In desperation I finally reversed the order of the if statement variables and to my surprise it worked. It doesn't make a lot of sense to me. I think it is a DOS parsing quirk but I only know it may be peculiar to Win7-64x. I would like to have someone with an XP or Vista or 7-32 machine copy paste the batch in my 1st post and try it and please report back.

BTW if you type: If "" equ "" echo equ, gives the desired response.
if """ equ "" gives an error message:
The syntax of the command is incorrect.
if "" equ "
The syntax of the command is incorrect
if " equ a do something
The syntax of the command is incorrect
if """ equ " echo something
echo was unexpected at this time.
if """" equ "" behaves somehow, so 2:1 and 1:1 ratio works where others do not
Try [] outside of the unbalanced "'s and it doesn't work either
It seems that if quotes are unbalanced on either side of the 'equ' or '==' DOS has a hissy fit. Jeb are you out there??

Many thanks in advance, Carl

foxidrive
Expert
Posts: 6031
Joined: 10 Feb 2012 02:20

Re: Command line parameter parsing issue

#4 Post by foxidrive » 19 Nov 2012 02:05

carlsomo wrote: In desperation I finally reversed the order of the if statement variables and to my surprise it worked.


There's no batch reason why it would. Test it again.

carlsomo
Posts: 91
Joined: 02 Oct 2012 17:21

Re: Command line parameter parsing issue

#5 Post by carlsomo » 19 Nov 2012 02:18

Code: Select all

C:\testbatch>message.bat "Enter a string" 1

Version1
a was unexpected at this time.

C:\testbatch>message.bat "enter a string" 2

Version2
"enter a string"... is quoted


Would you please try running it on your own machine befor making assumptions in your reply?? thanks

carl

foxidrive
Expert
Posts: 6031
Joined: 10 Feb 2012 02:20

Re: Command line parameter parsing issue

#6 Post by foxidrive » 19 Nov 2012 02:59

Code: Select all

@echo off
set "msg=%~1"

echo(Version2
if %1 equ %msg% (echo %1... is not quoted) else (echo %1... is quoted)

pause

echo(Version1
if %msg% equ %1 (echo %1... is not quoted) else (echo %1... is quoted)

pause


There you go. Neither of them worked, and version two did fail differently.

d:\ABC>a "abc def" 1
Version2
Press any key to continue . . .
Version1
def was unexpected at this time.

carlsomo
Posts: 91
Joined: 02 Oct 2012 17:21

Re: Command line parameter parsing issue

#7 Post by carlsomo » 19 Nov 2012 03:52

foxidrive wrote:

Code: Select all

@echo off
set "msg=%~1"

echo(Version2
if %1 equ %msg% (echo %1... is not quoted) else (echo %1... is quoted)

pause

echo(Version1
if %msg% equ %1 (echo %1... is not quoted) else (echo %1... is quoted)

pause



There you go. Neither of them worked, and version two did fail differently.

d:\ABC>a "abc def" 1
Version2
Press any key to continue . . .
Version1
def was unexpected at this time.

Hmmm... OK here I go: Which version of windows are you on? Your version 2 (like mine) has an 'if then else' statement that should have only one of 3 outcomes before the pause:

1. echo "abc def"... is quoted
2. echo "abc def"... is not quoted (the first two are mutually exclusive and the only way out is....
3. AN ERROR MSG before the pause string: "Press any key to continue..."
The condition is equal or not? and both conditions echo so there must be an error message unless supressed ( >nul 2>&1) or some such thing.
The code is so simple yet it fails in one version due to behavior of the CMD parser, No? I think that version 1 fails due to the statement on the left of the EQU is not quoted, perhaps. 'If abc def' without quotes is bombing out before the equality sign is factored. When the quoted %1 is on the left the equality sign is perceived and the unquoted parameter on the right is immediately seen as unequl if not quoted and fully recognized if quoted. I am simply looking to this forum to help me with an explanation of this behavior that at first seems illogical but I may have just hit on the explanation. It must not be rocket science with so simple a problem but DOS has so many strange quirks that it takes tedious experimentation to get seemingly simple batch tasks to work sometimes. Quoting both sides of the euqation bombs out miseralby so the only solution is to make sure the only side with possible quotes is on the left. I have also found frustrating nuances that cause a program to run well on Win7 and not on XP and vica versa. ie whether a set/p= is surrounded by () or not.

sorry to rant, Carl :twisted:

reformatted by jeb

jeb
Expert
Posts: 1062
Joined: 30 Aug 2007 08:05
Location: Germany, Bochum

Re: Command line parameter parsing issue

#8 Post by jeb » 19 Nov 2012 04:35

Hi Carl,

carlsomo wrote:I have also found frustrating nuances that cause a program to run well on Win7 and not on XP and vica versa. ie whether a set/p= is surrounded by () or not.

I would be supprised, if you really found differences between XP and Win7 in handling batch files(there are some, but normally the most people don't know those constructs).
Please show some samples.

Btw. You "IF/EQUAL/QUOTE" problem can be solved simply with delayed expansion.

Code: Select all

set "msg=%~1"
set "msgOrg=%1"
if !msg! EQU !msgOrg! (echo %1... is not quoted) else (echo %1... is quoted)
This works, as delayed expansion is not affected by quotes or any special characters

jeb

Aacini
Expert
Posts: 1932
Joined: 06 Dec 2011 22:15
Location: México City, México
Contact:

Re: Command line parameter parsing issue

#9 Post by Aacini » 19 Nov 2012 04:55

This is the method I use to make this check:

Code: Select all

@echo off
set param=%1
set param=%param:"= %
if "%param:~0,1%" equ " " (
   echo Param quoted
   set param=%~1
) else (
   echo Param unquoted
)
echo Param: [%param%]
Check this:

Code: Select all

if one two three equ one echo Fail at "two"
if one two three equ one two three Fail at "two" for the same reason
if one equ one two three echo Works, but try to execute "two"

If you insert any unbalanced quote in the IF comparison, it fails...

Antonio

foxidrive
Expert
Posts: 6031
Joined: 10 Feb 2012 02:20

Re: Command line parameter parsing issue

#10 Post by foxidrive » 19 Nov 2012 05:18

carlsomo wrote:Hmmm... OK here I go: Which version of windows are you on?


Windows 8.

Here is Windows 2000

C:\Documents and Settings\Administrator\Desktop>a "123 456" 3
Version2
Press any key to continue . . .
Version1
456 was unexpected at this time.


and here is Windows XP

c:\abc>a "aaa bbb" 2
Version2
Press any key to continue . . .
Version1
bbb was unexpected at this time.


Both of those were VMs.

dbenham
Expert
Posts: 2461
Joined: 12 Feb 2011 21:02
Location: United States (east coast)

Re: Command line parameter parsing issue

#11 Post by dbenham » 19 Nov 2012 05:24

I generally do not worry about whether the parameter was quoted or not because I store the parameter unquoted using set "param=%~1" and then I either add quotes at expansion as needed or else I use delayed expansion.

But back when I used to worry about quotes I tested like so:

Code: Select all

@echo off
setlocal
set param=%1
if not defined param (
  echo param is missing
) else if "%param:~0,1%%param:~0,1%" equ """" (
  echo %param% is quoted
) else (
  echo %param% is unquoted
)


Dave Benham

carlsomo
Posts: 91
Joined: 02 Oct 2012 17:21

Re: Command line parameter parsing issue

#12 Post by carlsomo » 19 Nov 2012 21:10

jeb

the delayed expansion with quoted strings is a great solution, thanks. As I recall I had a batch routine that used set/p="%$Bs%..." with the $Bs set to non destructive backspace and it worked fine in Win 7 but not in XP. When I removed the quotes it worked in XP. I think I also had some sep/p= statements with () around them I had to remove to get the XP version to behave the same. Now both versions are the same and work on both so I can only tell you the discrepancies from recollection.

BTW i am a guy who used to program in standard C lanuage 25+ yrs ago and used some batch here and there for user menus in the old DOS pre windows days. My skills were not used again until recently. I am running a small office that cannot afford to pay programmers and I lost my C skills. So I am writing many user interactive routines in Win CMD/batch where user input like choice and set/p are problematic and have limitations galore.

Thanks to the wisdom shared on the Dostips site I have been able to write a readline.bat script with command line parameter options to replace the 'set/p var=' and take tighter control of the keyboard and filter out poison characters that only mess up my scripts. Many thanks to jeb, dbenham, foxdrive, Antonio Perez Ayala (getkey.exe from stored hex is a Godsend), and other notables who post solutions here and help sovle problems that guys like myself are searching for. I have been able to improve productivity at the office by writing Batch scripts to handle tedious tasks and reduce human errors. This site is an awesome resource. BTW I am happy to share readline.bat with anyone who may be interested?

Here is the first part:

Code: Select all

@echo off&goto :start
:ReadLine.bat assigns user input to variable argument passed as %~1
echo(&echo(SYNTAX:
echo(ReadLine.bat Var=["prompt"] [/L=MaxLen] [/M] [/O] [/N ^| /I ^| /D ^| /T]
echo(
echo(Description:
echo(   This tool allows the users to Enter a character string to be
echo(   stored in the environment variable specified as 'Var'
echo(   It is designed to be more programmer friendly than 'Set /P'
echo(   Intended for obtaining user string input in batch or cmd scripts
echo(   Illegal or special chars ^<^>=%%^&^| are ignored and not assigned
echo(   All instances of double "quotes" are replaced by single 'quotes'
echo(   Returns length of environment string 'Var' in errorlevel
echo(   Returns 0 for empty string and 'Var' is set to nul
echo(   Returns -27 if 'Esc' or 'Ctrl-C' is pressed and 'Var' is set to nul
echo(
echo(   Editing keys: Home, End, Left, Right, Backspace, Del, Ins may be used
echo(
echo(Parameter List:
echo(   Variable 'Var' must be the first argument. All others are optional.
echo(   Prompt must be quoted if it contains spaces, ie. "Enter a string: "
echo(   /L = Length ^(Max string = 78 - 'prompt length' regardless of /L^)
echo(   /M will 'mask' input with the '*' character, ie. for passwords.
echo(   /O specifies starting in overstrike mode rather than insert default.
echo(   /N specifies only numeric characters, including '-,.' are allowed.
echo(   /I specifies only integer number, chars 0-9 and '-,' are allowed.
echo(   /D specifies Date format. Only numerals and '-/.' are allowed.
echo(   /T specifies Time format. Only numerals and ':.' are allowed.
echo(
echo(   Spaces are not allowed in any of the numeric formats: /N /I /D /T
echo(   No other formatting is performed. ie. 99/1234//5 is valid with /D
echo(
echo(   This routine requires GetKey.exe and it will be created in the
echo(   %%TEMP%% folder if not found in the current directory or %%PATH%%.
endlocal&exit/b %errorlevel%
:start main.....


Carl

Post Reply