在setlocals批处理

时间:2015-04-25 18:58:45

标签: batch-file

尝试在变量中保留感叹号。下面是一个简化的说明性脚本:

    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;发布完整的脚本" - 但是很长,这代表了核心问题。但是,如果有帮助,很乐意发帖。)

由于

1 个答案:

答案 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="