尝试在变量中保留感叹号。下面是一个简化的说明性脚本:
echo off
set testvar="C:\Windows\TestOfIllegals[!]"
echo Pre-EnableDE: %testvar%
setlocal enableextensions enabledelayedexpansion
echo Post-EnableDE: %testvar%
Setlocal DisableDelayedExpansion
echo ssetlocal sub-instance...
echo TestVar after re-disableDE: %testvar%
set modTestVar=%testvar%
echo TestVar to new var, modTestVar: %modTestVar%
endlocal & set "RetVar2=%modTestVar%"
echo modTestVar back in main script: %RetVar2%
Setlocal DisableDelayedExpansion
echo modTestVar, main script in another setlocal diasbleDE instance: %RetVar2%
endlocal
pause
exit /b
这会产生输出:
Pre-EnableDE: "C:\Windows\TestOfIllegals[!]"
Post-EnableDE: "C:\Windows\TestOfIllegals[]"
ssetlocal sub-instance...
TestVar after re-disableDE: "C:\Windows\TestOfIllegals[!]"
TestVar to new var, modTestVar: "C:\Windows\TestOfIllegals[!]"
modTestVar back in main script: "C:\Windows\TestOfIllegals[]"
modTestVar, main script in another setlocal diasbleDE instance: "C:\Windows\TestOfIllegals[]"
为什么modTestVar中没有保留感叹号?有没有办法做到这一点?
(我知道之前有人说过#34;发布完整的脚本" - 但是很长,这代表了核心问题。但是,如果有帮助,很乐意发帖。)
由于
答案 0 :(得分:9)
它保留在变量中,但您需要使用延迟扩展。
当您在延迟扩展模式下使用百分比扩展时,变量将被扩展,并且内容(尤其是将要解析的感叹号)也将在稍后进行解析,并且只会删除一个感叹号。
echo off
set testvar="C:\Windows\TestOfIllegals[!]"
echo Pre-EnableDE: %testvar%
setlocal enableextensions enabledelayedexpansion
echo Post-EnableDE: !testvar!
Setlocal DisableDelayedExpansion
echo ssetlocal sub-instance...
echo TestVar after re-disableDE: %testvar%
set modTestVar=%testvar%
echo TestVar to new var, modTestVar: %modTestVar%
endlocal & set "RetVar2=%modTestVar%"
echo modTestVar back in main script: !RetVar2!
Setlocal DisableDelayedExpansion
echo modTestVar, main script in another setlocal diasbleDE instance: %RetVar2%
endlocal
pause
另一个/唯一的问题是当您尝试在端点屏障(例如endlocal & set "RetVar2=%modTestVar%"
)上传输变量时。
这非常重要。
这是一个批处理宏,就像这样使用
%endlocal% modTestVar
setlocal DisableDelayedExpansion
set LF=^
set ^"\n=^^^%LF%%LF%^%LF%%LF%^^"
%= I use EDE for EnableDelayeExpansion and DDE for DisableDelayedExpansion =%
set ^"endlocal=for %%# in (1 2) do if %%#==2 (%\n%
setlocal EnableDelayedExpansion%\n%
%= Take all variable names into the varName array =%%\n%
set varName_count=0%\n%
for %%C in (!args!) do set "varName[!varName_count!]=%%~C" ^& set /a varName_count+=1%\n%
%= Build one variable with a list of set statements for each variable delimited by newlines =%%\n%
%= The lists looks like --> set result1=myContent\n"set result1=myContent1"\nset result2=content2\nset result2=content2\n =%%\n%
%= Each result exists two times, the first for the case returning to DDE, the second for EDE =%%\n%
%= The correct line will be detected by the (missing) enclosing quotes =%%\n%
set "retContent=1!LF!"%\n%
for /L %%n in (0 1 !varName_count!) do (%\n%
for /F "delims=" %%C in ("!varName[%%n]!") DO (%\n%
set "content=!%%C!"%\n%
set "retContent=!retContent!"set !varName[%%n]!=!content!"!LF!"%\n%
if defined content (%\n%
%= This complex block is only for replacing '!' with '^!' =%%\n%
%= First replacing '"'->'""q' '^'->'^^' =%%\n%
set ^"content_EDE=!content:"=""q!"%\n%
set "content_EDE=!content_EDE:^=^^!"%\n%
%= Now it's poosible to use CALL SET and replace '!'->'""e!' =%%\n%
call set "content_EDE=%%content_EDE:^!=""e^!%%"%\n%
%= Now it's possible to replace '""e' to '^', this is effectivly '!' -> '^!' =%%\n%
set "content_EDE=!content_EDE:""e=^!"%\n%
%= Now restore the quotes =%%\n%
set ^"content_EDE=!content_EDE:""q="!"%\n%
) ELSE set "content_EDE="%\n%
set "retContent=!retContent!set "!varName[%%n]!=!content_EDE!"!LF!"%\n%
)%\n%
)%\n%
%= Now return all variables from retContent over the barrier =%%\n%
for /F "delims=" %%V in ("!retContent!") DO (%\n%
%= Only the first line can contain a single 1 =%%\n%
if "%%V"=="1" (%\n%
%= We need to call endlocal twice, as there is one more setlocal in the macro itself =%%\n%
endlocal%\n%
endlocal%\n%
) ELSE (%\n%
%= This is true in EDE =%%\n%
if "!"=="" (%\n%
if %%V==%%~V (%\n%
%%V !%\n%
)%\n%
) ELSE IF not %%V==%%~V (%\n%
%%~V%\n%
)%\n%
)%\n%
)%\n%
) else set args="