Page 1 of 1

SET /P prompt mechanics - New behavior: = makes syntax error

Posted: 13 Jan 2013 13:20
by dbenham
I have seen a number of peculiarities documented with how SET /P handles prompts. And there are known differences between XP and later versions of Windows.

We had a significant discussion of the issues at viewtopic.php?p=16857.

Recently I saw a shocking complication posted at http://stackoverflow.com/a/14282332/1012053 that states a SET /P message cannot begin with =. I tested, and David Ruhmann is correct, it results in a syntax error :shock: :(

There doesn't appear to be any way to escape the =. And putting the prompt in a variable and using delayed expansion doesn't help either. :(

I can't believe I've never experienced this before, nor have I seen this documented elsewhere. I imagine someone must have seen this before.

Anyway, I decided to test XP, Vista, and Windows 7 to try to come up with a definitive set of SET /P prompt rules. Here is what I came up with.

Code: Select all


Syntax                |  XP                                 |  Vista and Windows 7
----------------------+-------------------------------------+-------------------------------------
<nul set /p =!msg!    |- If 1st char is quote, then trims   |- Trims leading white space chars.   
       or             |  that quote, and if at least one    |- If 1st non white space char is     
<nul set /p "=!msg!"  |  additional quote, than trims last  |  quote, then that quote is treated 
                      |  quote and all remaining chars.     |  as white space and trimmed, and if
                      |- If 1st non trimmed char is =, then |  at least one additional quote, then
                      |  syntax error.                      |  trims last quote and all remaining
                      |                                     |  chars.
                      |                                     |- If 1st non trimmed char is =, then
                      |                                     |  syntax error.
----------------------+-------------------------------------+-------------------------------------
<nul set /p ="!msg!"  |- Trims leading control chars and    |- Trims leading white space chars.
       or             |  spaces.                            |- If 1st non trimmed char is =, then
<nul set /p "="!msg!""|- If 1st non trimmed char is =, then |  syntax error.
                      |  syntax error.                      |
----------------------+-------------------------------------+-------------------------------------

On Vista and Windows 7, the trimmed leading white space chars are:
    9  0x09  Horizontal Tab
   10  0x0A  New Line
   11  0x0B  Vertical Tab
   12  0x0C  Form Feed
   13  0x0D  Carriage Return
   32  0x20  Space
  255  0xFF  Non-breaking Space


Example                           | XP result            | Vista/Win 7 result
----------------------------------+----------------------+--------------------
<nul set /p = hello world         | [ hello world]       | [hello world]
                                  |                      |
<nul set /p =" hello "world       | [hello ]             | [hello ]
                                  |                      |
<nul set /p "=" hello "world"     | [hello ]             | [hello ]
                                  |                      |
<nul set /p =" " hello "world"    | [" hello "world]     | [" hello "world]
                                  |                      |
<nul set /p "=" " hello "world""  | [" hello "world]     | [" hello "world]
                                  |                      |
<nul set /p = " hello "world      | [ " hello "world]    | [hello ]
                                  |                      |
<nul set /p "= " hello "world"    | [ " hello "world]    | [hello ]
                                  |                      |
<nul set /p = " " hello "world"   | [ " " hello "world"] | [" hello "world]
                                  |                      |
<nul set /p "= " " hello "world"" | [ " " hello "world"] | [" hello "world]
                                  |                      |
<nul set /p ==hello world         | syntax error         | syntax error
                                  |                      |
<nul set /p= =hello world         | [ =hello world]      | syntax error
                                  |                      |
<nul set /p "=" = hello "world"   | syntax error         | syntax error
                                  |                      |
<nul set /p "= " = hello "world"  | [ " = hello "world]  | syntax error

*Note: Square brackets are obviously not in the ouput :)


Note: jeb has posted a great alternative to SET /P :
"Output text without linefeed, even with leading space or =" at http://www.dostips.com/forum/viewtopic.php?f=3&t=4213
:D


Dave Benham

Re: SET /P prompt mechanics - New behavior: = makes syntax e

Posted: 13 Jan 2013 15:42
by foxidrive
I found this out here but I didn't clarify it.

viewtopic.php?p=22107#p22107

but SET /p can't handle = and "

A single leading quote doesn't work either.

Re: SET /P prompt mechanics - New behavior: = makes syntax e

Posted: 13 Jan 2013 16:07
by dbenham
foxidrive wrote:I found this out here but I didn't clarify it.

viewtopic.php?p=22107#p22107

but SET /p can't handle = and "

A single leading quote doesn't work either.

Good, you found the = problem as well. :)

But I don't see a problem with " as long as additional quotes are placed appropriately. As I stated in my post, the following both preserve quotes in !msg! (assume delayed expansion enabled)

Code: Select all

<nul set /p ="!msg!"
<nul set /p "="!msg!""


Dave Benham

Re: SET /P prompt mechanics - New behavior: = makes syntax e

Posted: 13 Jan 2013 16:22
by foxidrive
dbenham wrote:
foxidrive wrote:A single leading quote doesn't work either.


But I don't see a problem with " as long as additional quotes are placed appropriately.


Try it with just one quote, Dave. It no worky.

Re: SET /P prompt mechanics - New behavior: = makes syntax e

Posted: 13 Jan 2013 16:50
by Ed Dyreen
foxidrive wrote:Try it with just one quote, Dave. It no worky.
On XP a single quote works as long as additional quotes are placed appropriately,

Code: Select all

><nul set /p ="""
"
>
but '=' character at the beginning is a problem indeed. Next test is funny also :)

Code: Select all

>=
>==
>===
>
No syntax error, but nothing happens either, a valid command that does nothing at all :roll: :?:

Re: SET /P prompt mechanics - New behavior: = makes syntax e

Posted: 13 Jan 2013 16:56
by foxidrive
Can you make this work? echo "abc ?

Code: Select all

<nul set /p ="abc

Re: SET /P prompt mechanics - New behavior: = makes syntax e

Posted: 13 Jan 2013 17:31
by dbenham
foxidrive wrote:Can you make this work? echo "abc ?

Code: Select all

<nul set /p ="abc

Try reading my post at the top more carefully - it explains the rules.

Yes, your code will strip the quote. But that is not the correct syntax.

If you want to output nearly any message, including quotes, then you need extra quotes enclosing the string after the =.

Code: Select all

<nul set /p =""abc"

The extra quotes are part of the syntax, not part of the message! Nearly any message can be put within the quotes, except for the exceptions listed in my top post.


Dave Benham

Re: SET /P prompt mechanics - New behavior: = makes syntax e

Posted: 14 Jan 2013 10:44
by DigitalSnow
I have found a solution for the = equals and space trimming issue. However it requires placing a non-display character into the batch script. I do not know if it works on any version of Windows. Only tested on Windows 7.

Code: Select all

<nul set /p =".[0x08]%Var%"

Place any non-space non-issue character followed by the backspace character (illustrated by [0x08]) and only the value of %Var% will display.

Also from what I read here http://www.robvanderwoude.com/type.php, there is an issue with the 0xFF character when the codepage is not 1252.

As noted by foxidrive, Yes this is only a solution for displaying to the screen because the non-displayed characters will be redirected to a file.

BTW: I'm David from Stack Overflow.

Re: SET /P prompt mechanics - New behavior: = makes syntax e

Posted: 14 Jan 2013 10:48
by foxidrive
That's probably fine for display purposes but when redirecting into a file it's going to be an issue.

Re: SET /P prompt mechanics - New behavior: = makes syntax e

Posted: 14 Jan 2013 10:57
by DigitalSnow
Oh, and the reason the equals sign does not work at the beginning, is due to this limitation which is listed in the set /? help documentation.
SET command will not allow an equal sign to be part of the name of a variable.

When the first character is set as an equals sign it thinks that we are trying to set the variable name containing an equals sign. This was further made evident as an issue by the leading space trimming in Vista+.

Re: SET /P prompt mechanics - New behavior: = makes syntax e

Posted: 14 Jan 2013 22:47
by dbenham
DigitalSnow wrote:Oh, and the reason the equals sign does not work at the beginning, is due to this limitation which is listed in the set /? help documentation.
SET command will not allow an equal sign to be part of the name of a variable.

When the first character is set as an equals sign it thinks that we are trying to set the variable name containing an equals sign. This was further made evident as an issue by the leading space trimming in Vista+.

I suppose that could be true, but it is inconsistent with how the normal SET command works, and nonsensical.

SET "varName==varValue" - the variable name ends at the first = and the 2nd = is included as part of the value.

SET /P "varName==Prompt" - the statement fails because it tries to include the first = in the variable name :?:

Then why does it work if there is an intervening character?

SET /P "varName=x=abc" - the variable name ends at the first = and the remainder is part of the prompt.

I can't see a rational explanation why the prompt cannot begin with =. I should think the variable name should always end at the first =, and the remainder should be the prompt. But then batch is full of irrational quirks and hacks. :evil:


Dave Benham

Re: SET /P prompt mechanics - New behavior: = makes syntax e

Posted: 15 Jan 2013 02:18
by carlos
A fix for the problem:

Code: Select all

@Echo Off
For /F %%# in ('"Prompt;$H;&For %%_ in (1) Do Rem"'
) Do Set "\b=%%#"
Set /P "=%\b%=Equal" <Nul
Pause >Nul

Re: SET /P prompt mechanics - New behavior: = makes syntax e

Posted: 15 Jan 2013 02:37
by foxidrive
carlos wrote:A fix for the problem:


It's only a fix for displaying. If you redirect into a file then it will have a leading hex 08 character.

Re: SET /P prompt mechanics - New behavior: = makes syntax e

Posted: 15 Jan 2013 07:49
by DigitalSnow
dbenham wrote:
DigitalSnow wrote:Oh, and the reason the equals sign does not work at the beginning, is due to this limitation which is listed in the set /? help documentation.
SET command will not allow an equal sign to be part of the name of a variable.

When the first character is set as an equals sign it thinks that we are trying to set the variable name containing an equals sign. This was further made evident as an issue by the leading space trimming in Vista+.

I suppose that could be true, but it is inconsistent with how the normal SET command works, and nonsensical.

SET "varName==varValue" - the variable name ends at the first = and the 2nd = is included as part of the value.

SET /P "varName==Prompt" - the statement fails because it tries to include the first = in the variable name :?:

Then why does it work if there is an intervening character?

SET /P "varName=x=abc" - the variable name ends at the first = and the remainder is part of the prompt.

I can't see a rational explanation why the prompt cannot begin with =. I should think the variable name should always end at the first =, and the remainder should be the prompt. But then batch is full of irrational quirks and hacks. :evil:


Dave Benham

I agree that it is inconsistent. You would think that set would parse the variable name using the same method for both set [variable=[string]] and set /p variable=[promptString], but sadly that is not the case. :( Nor does it appear to have ever been the case. My guess is that the programmers who wrote set did not use the same function for parsing the string as they did with the promptString.