使用 set /p 更新批处理脚本的变量总是包含最后一个值

Jon*_*ert 3 windows cmd batch-file

我正在尝试使用 set /p 命令在循环中调整 Windows 批处理变量。键盘输入后,变量仍包含旧值。我读过通过 set /p 设置的变量只有局部范围。但我不明白“本地”在这里的真正含义。

@echo off
setlocal EnableDelayedExpansion

set a=4
echo Inital A: %a%

:LoopLabel
MODE | find %a% >nul 2>&1
IF %ERRORLEVEL% NEQ 0 (
    set /p "a=enter new a: "
    echo a=%a%
    goto LoopLabel
)
Run Code Online (Sandbox Code Playgroud)

输出是:

Inital A: 4
enter new a: 5
a=4
enter new a: 6
a=5
enter new a: 7
a=6
Run Code Online (Sandbox Code Playgroud)

有没有人有想法,我能解释一下为什么会这样吗?

非常感谢,强尼

Lin*_*ple 6

在 IF 中执行代码是问题所在。看一下这个:

@echo off

set a=4
echo Inital A: %a%

:LoopLabel
MODE | find "%a%" >nul 2>&1
IF %ERRORLEVEL% EQU 0 goto stuff
    set /p "a=enter new a: "
    echo a=%a%
    goto LoopLabel
:stuff
Run Code Online (Sandbox Code Playgroud)

set /p执行IF之外,所以它工作正常,即使没有延迟扩展。

IF 块中的所有命令同时(并行)进行评估,因此当

echo a=%a%
Run Code Online (Sandbox Code Playgroud)

运行,它不知道由分配的任何新值

set /p "a=enter new a: "
Run Code Online (Sandbox Code Playgroud)

为了进一步澄清,您a实际上确实包含新值,但echo a=%a%使用旧值执行。

一种解决方案是使用 IF 和标签来获得预期的程序流程,同时避免在 IF 块内执行多​​步。

此外,find除非您输入的值被引用或在将%a%其提供给find.

或者,您可以对您的a值使用延迟扩展,以在“set /p更改”后获取其值。

要做到这一点,你会改变

echo a=%a%
Run Code Online (Sandbox Code Playgroud)

echo a=!a!
Run Code Online (Sandbox Code Playgroud)

我在批处理中知道的唯一可变范围是%1...%9%*in called 标签。否则一切都是全局的,包括你的aset by set /p

  • 也许您希望 enabledDelayedExpansion 会更有帮助。试试`echo a=!a!` (2认同)