1

为了在文本文件中的变量中存储多行,我使用了这个问题的答案:https ://stackoverflow.com/a/10624240/1513458

使用这个脚本内联并解析大文件给了我一个最大的 setlocal 错误。所以为了解决这个问题,我将脚本放在一个子程序中,并从我需要它的行中调用它。

子例程底部的回显在它终止之前会输出预期的结果……但回到最初调用它的顶部,变量是空的。这是为什么?

这是脚本的缩短版本:

setlocal EnableDelayedExpansion
set sourcefile=cc1
call :readfile %sourcefile%
echo !insert!
goto :EOF

:readfile
SETLOCAL DisableDelayedExpansion
set "insert="
FOR /F "usebackq delims=" %%a in (`"findstr /n ^^ %SOURCELOC%\%1.txt"`) do (
    set "line=%%a"
    SETLOCAL EnableDelayedExpansion
    set "line=!line:#=#S!"
    set "line=!line:*:=!"
    for /F "delims=" %%p in ("!insert!#L!line!") do (
        ENDLOCAL
        set "insert=%%p"
    )
)
SETLOCAL EnableDelayedExpansion
if defined insert (
set "insert=!insert:~2!"
set ^"insert=!insert:#L=^

!"
set "insert=!insert:#S=#!"
)
rem A echo !insert! here would output the expected result
goto :EOF

非常感谢你们的帮助。批次显然不适合我,但我需要坚持这一点。

4

2 回答 2

3

您的 :readfile 例程在顶部有 SETLOCAL,用于本地化环境更改。当例程结束时,对于在例程中实例化的每个活动 SETLOCAL 都会执行一个隐式 ENDLOCAL。因此环境恢复到调用之前存在的状态。

不需要调用的子程序。您之前的代码在 FOR 循环中必须有没有 ENDLOCAL 的 SETLOCAL。这将导致最大 SETLOCAL 错误。现在你的 FOR 循环已经配对了 SETLOCAL/ENDLOCAL,所以没有更多问题了。

可以跨 ENDLOCAL 屏障传输任何值,但它使用了一种先进的技术。

一些简单的重组避免了这样做的需要。但要小心 - 批处理变量不能包含超过 8192 个字符。

setlocal disableDelayedExpansion
set sourcefile=cc1

set "insert="
for /f "delims=" %%a in ('findstr /n "^" "%SOURCELOC%\%~1.txt"') do (
  set "line=%%a"
  setlocal EnableDelayedExpansion
  set "line=!line:#=#S!"
  set "line=!line:*:=!"
  for /f "delims=" %%p in ("!insert!#L!line!") do (
    endlocal
    set "insert=%%p"
  )
)
setlocal EnableDelayedExpansion
if defined insert (
set "insert=!insert:~2!"
set ^"insert=!insert:#L=^

!"
set "insert=!insert:#S=#!"
)
echo !insert!


编辑

这是一个演示跨 ENDLOCAL 边界返回任何值的解决方案(除了它不支持回车。有一个简单的扩展支持回车)。该例程将给出正确的结果,无论它是在启用还是禁用延迟扩展的情况下调用的。该技术是由 DosTips 用户 jeb 开发的: http://www.dostips.com/forum/viewtopic.php?f=3&t=1839和此处:http : //www.dostips.com/forum/viewtopic.php ?p=6930#p6930。在那里你会找到一些关于它是如何工作的解释,但它不适合胆小的人。

@echo off
setlocal enableDelayedExpansion
set sourceloc=.
set sourcefile=test
set ^"LF=^

^"
call :readFile "%sourcefile%"
echo(!insert!
exit /b

:readFile
setlocal
set "notDelayed=!"

setlocal disableDelayedExpansion
set "insert="
for /f "delims=" %%a in ('findstr /n "^" "%SOURCELOC%\%~1.txt"') do (
  set "line=%%a"
  setlocal EnableDelayedExpansion
  set "line=!line:%%=%%J!"
  set "line=!line:*:=!"
  for /f "delims=" %%p in ("!insert!%%~L!line!") do (
    endlocal
    set "insert=%%p"
  )
)
setlocal enableDelayedExpansion
if defined insert (
  set "insert=!insert:"=%%~K!"
  if not defined notDelayed set "insert=!insert:^=^^^^!"
)

if defined insert if not defined notDelayed set "insert=%insert:!=^^^!%" Do not remove!
set "replace=%% """"
for %%L in ("!LF!") do for /f "tokens=1,2" %%J in ("!replace!") do (
  endlocal
  endlocal
  endlocal
  set "insert=%insert%" Do not remove!
)
exit /b
于 2013-08-05T16:44:28.963 回答
0

尝试这个:

setlocal EnableDelayedExpansion
set sourcefile=cc1
call :readfile insert
echo %insert%
goto :EOF

:readfile
SETLOCAL DisableDelayedExpansion
set "insert="
FOR /F "delims=" %%a in ('findstr /n "^" "%SOURCELOC%\%1.txt"') do (
     set "line=%%a"
     SETLOCAL EnableDelayedExpansion
     set "line=!line:#=#S!"
     set "line=!line:*:=!"
     for /F "delims=" %%p in ("!insert!#L!line!") do (
          ENDLOCAL
          set "insert=%%p"
     )
)
SETLOCAL EnableDelayedExpansion
if defined insert (
set "insert=!insert:~2!"
set ^"insert=!insert:#L=^

!"
set "insert=!insert:#S=#!"
)
rem A echo !insert! here would output the expected result
SET "%1=!insert!"
ENDLOCAL 
goto :EOF
于 2013-08-05T08:00:15.827 回答