batch-file - 批处理 - 如何在启用了启用延迟扩展的情况下设置并保留下一个命令的变量值

标签 batch-file cmd environment-variables

如果我没有设置enabledelayedexpansionif block 内的变量值不会立即改变,直到出去。但如果我将其设置为打开,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 的扩展 block 内设置的变量。并且 EnableDelayedExpansion 必须在本地启用和结束,以免扰乱全局变量。我选择了带有 goto 的选项,但我使用 callexit 来代替。

最佳答案

一个简单的解决方案是使用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

自 Windows Vista 起,命令 CHOICE 默认可用,对于 Windows Server 2003 起的 Windows 服务器版本,默认情况下可用。 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/P 并使用 delayed 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 窗口,在其中执行以下命令,并完整、仔细地阅读每个命令显示的帮助页面。

  • 选择/?
  • 回显/?
  • endlocal/?
  • 转到/?
  • 如果/?
  • 雷姆/?
  • 设置/?
  • setlocal/?

关于batch-file - 批处理 - 如何在启用了启用延迟扩展的情况下设置并保留下一个命令的变量值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61927255/

相关文章:

powershell - 以管理员身份从 cmd 批处理运行 PowerShell 脚本

batch-file - Nunit 结果 xml 在 Jenkins 构建期间未更新

unix - ftp mget 在脚本中使用时不起作用

java - 选择菜单,java中用户的选择

python - 当包含目录是 PYTHONPATH 的一部分并且文件存在时,为什么找不到 PYTHONPATH 中的模块?

windows-7 - 无法使用 Windows 命令提示符打印双字节字符

batch-file - 创建 cmd 快捷方式以在 Inno Setup 中执行批处理文件

django - 使用BAT文件一键启动Django项目

linux - 尝试在弹性 beanstalk 中添加盐和键作为环境变量(语法错误)

amazon-web-services - 用于拉取请求的 AWS Amplify 环境变量?