Page 1 of 1

Strange behavior of SET /P

Posted: 25 Sep 2021 23:01
by Alogon

Code: Select all

if 1==1 (
  set A=
  set /P A= [in parens] What shall A be?
  echo A=%A%
  )
set A=
set /P A=[not in parens] What shall A be?
echo A=%A%
Only the second set /P works properly. When the statement is in a parenthesized block, it does not set the variable.

While experimenting just now, I noticed two other anomalies. First, if the prompt string contains parentheses, they will probably produce an error. I originally wrote "(in parens)" instead of "[in parens]" and got the message "What was unexpected at this time."

Second, one of my attempted replies to the prompt was "hi". I happen to have a Doskey macro installed called HI. The value of A became the text of the macro line.

I'm already acquainted with a third caution: if the variable to be set is local but not yet existing, and there is a global variable with the same name, and the user just responds to the prompt with <enter>, then the variable will not be created. The program will instead reference the global variable. Hence it should be initialized before the set /P command. But in this example, the initialization within parentheses doesn't seem to work, either.

I hesitate even to predict what will happen under various circumstances. Either there is something rather basic that I don't understand about set /P, or the use of parentheses, or setlocal, or this is an unusually flaky command that must be used with caution. Can someone shed some light on my confusion?

Re: Strange behavior of SET /P

Posted: 25 Sep 2021 23:30
by ShadowThief
You're trying to set and use a variable within the same code block. By default, variables are expanded when the script is parsed, but things inside of parentheses are treated as a single command so %A% gets expanded to nothing because that's its value before the code block.

To tell the interpreter to expand the variables when the line is executed instead, enable delayed expansion and use the !A! syntax instead.

Code: Select all

@echo off
setlocal enabledelayedexpansion
if 1==1 (
  set A=
  set /P A= [in parens] What shall A be?
  echo A=!A!
  )
set A=
set /P A=[not in parens] What shall A be?
echo A=%A%

Re: Strange behavior of SET /P

Posted: 26 Sep 2021 05:38
by OJBakker
Use double quotes with the set command to avoid the errors with parentheses.
Use 'call echo' or 'set A' to see the up-to-date values of a variable in a () codeblock if you don't use delayed expansion.

Code: Select all

if 1==1 (
  set A=
  set /P "A= (in parens) What shall A be?"
  echo A=%A%
  rem 'call echo' shows the uptodate value of variable A
  @call echo A=%%A%%
  rem 'set A' shows all variables starting with A with their values
  @set A
  rem next line limits the output of 'set A' to just your variable A
  @if defined A @for /f "tokens=1,2* delims==" %%P in ('set A') do @if "%%P" == "A" @echo A=%%Q
  )
set A=
set /P "A=(not in parens) What shall A be?"
echo A=%A%
pause