【问题标题】:Batch: Concatenate two arbitrary strings outside SETLOCAL EnableDelayedExpansion批处理:在 SETLOCAL EnableDelayedExpansion 之外连接两个任意字符串
【发布时间】:2012-03-14 04:57:12
【问题描述】:

我需要连接两个字符串变量并将结果放回第一个变量中。这两个字符串可以包含任意个任意字符,如换行符、感叹号等。

主脚本运行延迟扩展禁用,所以我必须使用 SETLOCAL EnableDelayedExpansion 进行实际连接。我只是不知道如何将结果从本地返回到全局变量中。

我想避免使用临时文件。

我希望批处理文件允许在本地块之外延迟扩展。

谢谢。

编辑:

@杰布
我尝试使用您的内联代码,而不是在函数中,并且它有效。
然后我试着把它放在一个 FOR 循环中,结果打破了它。
循环中的函数调用 = 有效。
内联是一个循环 = 对我不起作用。
我现在不需要那个功能。这只是一个观察。
谢谢。

@echo off
REM Changed from function call to inline implementation
setlocal EnableDelayedExpansion
cls
for /f %%a in ('copy /Z "%~dpf0" nul') do set "CR=%%a"
set LF=^


rem TWO Empty lines are neccessary
set "original=zero*? %%~A%%~B%%~C%%~L!LF!one&line!LF!two with exclam^! !LF!three with "quotes^&"&"!LF!four with ^^^^ ^| ^< ^> ( ) ^& ^^^! ^"!LF!xxxxxwith CR!CR!five !LF!six with ^"^"Q ^"^"L still six "

setlocal DisableDelayedExpansion
SET result=""
REM call :lfTest result original
::::::::::::::::::::
for /L %%i in (1,1,2) do (
setlocal
set "NotDelayedFlag=!"
echo(
if defined NotDelayedFlag (echo lfTest was called with Delayed Expansion DISABLED) else echo lfTest was called with Delayed Expansion ENABLED
setlocal EnableDelayedExpansion
set "var=!original!"

rem echo the input is:
rem echo !var!
echo(

rem ** Prepare for return
set "var=!var:%%=%%~2!"
set "var=!var:"=%%~3!"
for %%a in ("!LF!") do set "var=!var:%%~a=%%~L!"
for %%a in ("!CR!") do set "var=!var:%%~a=%%~4!"

rem ** It is neccessary to use two IF's, else the %var% expansion doesn't work as expected
if not defined NotDelayedFlag set "var=!var:^=^^^^!"
if not defined NotDelayedFlag set "var=%var:!=^^^!%" !

set "replace=%% """ !CR!!CR!"
for %%L in ("!LF!") do (
   for /F "tokens=1,2,3" %%2 in ("!replace!") DO (
     ENDLOCAL
     ENDLOCAL
     set "result=%var%" !
     @echo off
   )
)
)
::::::::::::::::::::
setlocal EnableDelayedExpansion
echo The result with disabled delayed expansion is:
if !original! == !result! (echo OK) ELSE echo !result!

echo ------------------
echo !original!

pause
goto :eof

【问题讨论】:

  • 最后一次扩展 set "result=%var%" ! 在您的代码中失败,因为它现在在解析完整的 for /L %%i in (1,1,2) 块时扩展。但它应该在返回值之前扩展
  • 只是添加了一个“更短”和“更简单”的方式,但这不是一个“完美”的解决方案:-)

标签: string variables batch-file


【解决方案1】:

就像我在你的另一个问题中所说:Batch: Returning a value from a SETLOCAL EnableDelayedExpansion

只需点击链接即可获得“完美”解决方案

或者我可以在这里粘贴代码

rem ** Preparing CR and LF for later use
for /f %%a in ('copy /Z "%~dpf0" nul') do set "CR=%%a"
set LF=^


rem TWO Empty lines are neccessary

然后在你的函数开始时,检测delayedExpansion是关闭还是打开

setlocal
set "NotDelayedFlag=!"
setlocal EnableDelayedExpansion

在你的函数结束时,返回值

rem ** Prepare for return
set "var=!var:%%=%%~2!"
set "var=!var:"=%%~3!"
for %%a in ("!LF!") do set "var=!var:%%~a=%%~L!"
for %%a in ("!CR!") do set "var=!var:%%~a=%%~4!"

rem ** It is neccessary to use two IF's, else the %var% expansion doesn't work as expected
if not defined NotDelayedFlag set "var=!var:^=^^^^!"
if not defined NotDelayedFlag set "var=%var:!=^^^!%" !

set "replace=%% """ !CR!!CR!"
for %%L in ("!LF!") do (
   for /F "tokens=1,2,3" %%2 in ("!replace!") DO (
     ENDLOCAL
     ENDLOCAL
     set "%~1=%var%" !
     @echo off
      goto :eof
   )
)

编辑:变短一点
好的,这看起来有点复杂,在很多情况下可以通过其他技巧来解决。
如果您知道,您将从 EnableDelayed 切换回 DisableDelayed,并且您确定不使用任何 LF,FOR-RETURN 也会起作用。

@echo off
setlocal
call :myTest result
set result
goto :eof

:myTest
setlocal EnableDelayedExpansion
rem ... do something here
set "value=^!_&_%%_|_>"

echo --
for /f ^"eol^=^

^ delims^=^" %%a in ("!value!") do (
    endlocal
    set "%~1=%%a"
    goto :eof
) 

for /f ^"eol^=^.... 的拆分只是为了禁用 eol 字符。

【讨论】:

  • 哇,效果很好,谢谢。真的让我们欣赏现代编程语言,不是吗?只是一个简单的问题:如果我想返回参数 2、3 或 4 中的结果,我是否必须更改您使用的替换值,还是它们不相关?
  • for循环参数2,3,4会隐藏函数参数2,3,4。您可以简单地更改 for 循环参数
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-02-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多