批处理-如何设置并保留启用了enableelayedexpansion的下一个命令的变量值

问题描述 投票:2回答:1

如果我不将enabledelayedexpansion设置为开,则直到移出if块内的变量值都不会立即更改。但是,如果我将其设置为开,则x将在下一条命令中重置为先前的值。

setlocal enabledelayedexpansion
if defined x (
    set yes=
    set /p yes=Do you want to reset?
    if !yes! == y set x=
)
if not defined x set /p x=X:

我想要的只是我不想要的

  1. 在下一个命令上更改了值
  2. 值未立即更改

谢谢@ Mofi的答案。您的解决方案有效,但是我必须先删除setlocal EnableExtensions DisableDelayedExpansion,然后才能找出原因。因此,教训是我们无法立即读取刚刚在同一命令内设置的变量的新值,包括在没有EnableDelayedExpansion的扩展块内。并且必须启用EnableDelayedExpansion并在本地结束,以免与全局变量混淆。我用goto代替,但我改用callexit

batch-file cmd environment-variables
1个回答
2
投票

一个简单的解决方案是使用choice而不是set /P

@echo off
setlocal EnableExtensions DisableDelayedExpansion
if defined x (
    %SystemRoot%\System32\choice.exe /C NY /N /M "Do you want to reset? [N/Y]"
    if errorlevel 2 set "x="
)
if not defined x set /P "x=X: "
endlocal

命令CHOICE在Windows Vista和Windows Server 2003起默认为可用。CHOICE总是删除提示文本两侧的所有常规空格和水平制表符,然后自动追加提示文本后的空格。

set /P在不使用延迟的环境变量扩展的情况下可用于任何用户输入的一种非常安全的解决方案如下,默认情况下,N用于用户,根本不输入任何内容。

@echo off
setlocal EnableExtensions DisableDelayedExpansion
if not defined x goto PromptForX

set "yes=N"
set /P "yes=Do you want to reset? [N/Y] "
rem Remove all double quotes from user input string.
set "yes=%yes:"=%"
rem Has the user entered just one or more double quotes?
if not defined yes goto PromptForX
rem Now it is safe to compare the strings which cannot result anymore in a
rem syntax error caused by user input or doing something completely different
rem than the string comparison if the user input a command line which would
rem have changed this IF command line to a completely different command line.
if /I "%yes%" == "y" set "x="

:PromptForX
if not defined x set /P "x=X: "
endlocal

命令SET不会在提示符后添加空格。提示文本必须在批处理文件中定义的末尾带有空格。

[使用set /Pdelayed expansion的另一个安全解决方案是:

@echo off
setlocal EnableExtensions DisableDelayedExpansion
if defined x (
    set "yes=N"
    set /P "yes=Do you want to reset? [N/Y] "
    setlocal EnableDelayedExpansion
    if /I !yes! == y (endlocal & set "x=") else endlocal
)
if not defined x set /P "x=X: "
endlocal

首先使用endlocal还原先前的环境,然后Windows命令处理器执行下一个set "x=",以在用户实际输入yY的本地环境中取消定义此环境变量,而仅还原先前的环境。用户输入了其他任何内容或根本没有输入任何内容。有关操作员Single line with multiple commands using Windows batch file的更多信息,另请参见&

我建议也阅读this answer,以获取有关命令SETLOCALENDLOCAL的详细信息,以及这两个命令的每次执行在后台发生的情况。

有关这三种解决方案的完整说明,请阅读我的回答:How to stop Windows command interpreter from quitting batch file execution on an incorrect user input?

注意:如果在演示批处理文件之外还应使用新值定义环境变量endlocal,则将所有三个批处理文件的最后一行从endlocal & set "x=%x%"更改为x

为了了解所使用的命令及其工作方式,请打开command prompt窗口,在其中执行以下命令,并非常仔细地阅读每个命令显示的所有帮助页面。

  • choice /?
  • echo /?
  • endlocal /?
  • goto /?
  • if /?
  • rem /?
  • set /?
  • setlocal /?
热门问题
推荐问题
最新问题