DosTips.com

A Forum all about DOS Batch
It is currently 25 Sep 2016 18:09

All times are UTC-06:00




Post new topic  Reply to topic  [ 14 posts ] 
Author Message
PostPosted: 13 Jan 2013 13:20 
Offline
Expert

Joined: 12 Feb 2011 21:02
Posts: 1717
Location: United States (east coast)
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:

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


Last edited by dbenham on 16 Jan 2013 10:13, edited 1 time in total.

Top
   
PostPosted: 13 Jan 2013 15:42 
Offline
Expert

Joined: 10 Feb 2012 02:20
Posts: 5951
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.


Top
   
PostPosted: 13 Jan 2013 16:07 
Offline
Expert

Joined: 12 Feb 2011 21:02
Posts: 1717
Location: United States (east coast)
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:
<nul set /p ="!msg!"
<nul set /p "="!msg!""


Dave Benham


Top
   
PostPosted: 13 Jan 2013 16:22 
Offline
Expert

Joined: 10 Feb 2012 02:20
Posts: 5951
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.


Top
   
PostPosted: 13 Jan 2013 16:50 
Offline
Expert

Joined: 16 May 2011 08:21
Posts: 1433
Location: Flanders(Belgium)
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:
><nul set /p ="""
"
>
but '=' character at the beginning is a problem indeed. Next test is funny also :)
Code:
>=
>==
>===
>
No syntax error, but nothing happens either, a valid command that does nothing at all :roll: :?:


Top
   
PostPosted: 13 Jan 2013 16:56 
Offline
Expert

Joined: 10 Feb 2012 02:20
Posts: 5951
Can you make this work? echo "abc ?

Code:
<nul set /p ="abc


Top
   
PostPosted: 13 Jan 2013 17:31 
Offline
Expert

Joined: 12 Feb 2011 21:02
Posts: 1717
Location: United States (east coast)
foxidrive wrote:
Can you make this work? echo "abc ?

Code:
<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:
<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


Top
   
PostPosted: 14 Jan 2013 10:44 
Offline

Joined: 21 Dec 2012 13:36
Posts: 20
Location: United States
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:
<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.


Last edited by DigitalSnow on 14 Jan 2013 11:08, edited 2 times in total.

Top
   
PostPosted: 14 Jan 2013 10:48 
Offline
Expert

Joined: 10 Feb 2012 02:20
Posts: 5951
That's probably fine for display purposes but when redirecting into a file it's going to be an issue.


Top
   
PostPosted: 14 Jan 2013 10:57 
Offline

Joined: 21 Dec 2012 13:36
Posts: 20
Location: United States
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.
Quote:
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+.


Top
   
PostPosted: 14 Jan 2013 22:47 
Offline
Expert

Joined: 12 Feb 2011 21:02
Posts: 1717
Location: United States (east coast)
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.
Quote:
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


Top
   
PostPosted: 15 Jan 2013 02:18 
Offline

Joined: 20 Aug 2010 13:57
Posts: 426
Location: Chile
A fix for the problem:
Code:
@Echo Off
For /F %%# in ('"Prompt;$H;&For %%_ in (1) Do Rem"'
) Do Set "\b=%%#"
Set /P "=%\b%=Equal" <Nul
Pause >Nul


Top
   
PostPosted: 15 Jan 2013 02:37 
Offline
Expert

Joined: 10 Feb 2012 02:20
Posts: 5951
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.


Top
   
PostPosted: 15 Jan 2013 07:49 
Offline

Joined: 21 Dec 2012 13:36
Posts: 20
Location: United States
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.
Quote:
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.


Top
   
Display posts from previous:  Sort by  
Post new topic  Reply to topic  [ 14 posts ] 

All times are UTC-06:00


Who is online

Users browsing this forum: Baidu [Spider], Bing [Bot], Google [Bot], Yahoo [Bot] and 2 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Limited