我发现这里似乎是对我问题的解释
DOS batch: Why are my set commands resulting in nothing getting stored?
但我真的不明白这个解释。
这是我的剧本......
for /R /d %%f in (\Product\Database\SQL\Project\Model\Scripts\*) DO (
REM echo %%f
SET !LOAD_FILE_FILTER= %%f\*.sql
echo file: %!LOAD_FILE_FILTER%
CALL %!BATCH_FILE% -u %!USER_NAME% -p %!PASSWORD% -s %!SERVER_NAME% -d %!DATABASE_NAME% -f %!LOAD_FILE_FILTER% -o %!LOG_FILE%
IF %!EchoErrors%==1 (
ECHO [
TYPE %!LOG_FILE%
ECHO ]
)
)
echo始终打印文件:* .sql,我传递此var的脚本总是抱怨LOAD_FILE_FILTER为空。
我已尝试按照文章中的建议添加setlocal EnableDelayedExpansion
,但它无法解决问题。 echo file: %!LOAD_FILE_FILTER%
始终打印我正在运行的目录中的最后一个子目录。 echo %%f
始终打印正确的值。
'!'是什么变量后面为我做了什么?
另一方面,有人可以向我解释
之间的区别SET!VAR 和 SET VAR
%VAR&安培; &安培;!VAR和放大器; !VAR! %% VAR
答案 0 :(得分:6)
我们将从一个简单的案例开始
set "var="
set "var=test"
echo %var%
读取代码后,它会删除变量的内容,为其赋予一个新值并回显它。
让我们稍微改变一下连接最后两个命令
set "var="
set "var=test" & echo %var%
“相同”代码,但在这种情况下,输出到控制台不会显示变量中的值。
为什么呢?在批处理文件中,将解析然后执行要执行的行。在解析阶段,每个变量读取操作(在此处检索变量的值)将替换为在解析时存储在变量内的值。完成此操作后,将执行生成的命令。因此,在解析第二行的上一个示例中,它将转换为
set "var=test" & echo
现在,线路上没有读取操作,没有回显值,因为当线路被加入时,变量没有任何值(它将在执行线路时分配),因此读取操作已经没有任何东西。此时,执行代码并且感知到的行为是set
命令失败,因为我们没有将“明显”值回显到控制台。
在块中也可以找到此行为。块是括在括号中的一组行(通常是for
和if
构造),并由解析器处理,就好像块中的所有行只有一行具有连接命令一样。重写完整块,删除所有变量读取操作并用变量内部的值替换,然后执行内部没有变量引用的完整块。
在执行时,对块内的变量没有读取操作,只有其初始值,因此,在同一块内部无法检索分配给块内变量的任何值,因为没有任何读取操作
所以,在这段代码中
set "test=before"
if defined test (
set "test=after"
echo %test%
)
在执行第一个set
之后,将解析块(if
命令及其括号中包含的所有代码)并将其转换为
if defined test (
set "test=after"
echo before
)
显示“错误”值。
处理它的常用方法是使用延迟扩展。它允许您在需要时更改语法以将变量从%var%
读取到!var!
,向解析器指示在分析时不能删除读取操作,而是延迟到命令被执行。
setlocal enabledelayedexpansion
set "var="
set "var=test" & echo !var!
现在的第三行在解析时转换为
set "var=test" & echo !var!
是的,不删除变量引用。读取操作将延迟,直到执行echo
命令,此时变量的值已更改。
所以
%var%
是一个变量引用,将在分析时替换
!var!
是一个将在执行时替换的变量引用
%x
单个字符的 x
通常是for
可替换参数,该变量将保持当前元素的交互。就其本身而言,将在执行时扩展。在命令行中使用带有单个百分号的语法。批处理文件内部需要转义百分号,引用可替换参数的语法为%%x