2013-08-05 39 views
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 

非常感谢你们的帮助。批量显然不适合我,但我需要通过强化这一点。

+0

您是否真的需要一个变量中的所有行,或者是否可以更简单地使用_array_,每个变量一行? – jeb

回答

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 
+0

阅读我提供的链接答案。脚本不会丢失;因为每行都以XXX:作为前缀,按照findstr中的/ N。 – TurdPile

+0

再加上您提供的代码(内联)与我所拥有的代码完全相同,除了%〜1之外,这是导致主要问题开始的原因。 Setlocal被称为太多。把它作为子程序的全部原因是隐式的endlocals。 - 除非我错过了代码中所做的更改,否则我不会看到问题有任何不同。 – TurdPile

+0

@TurdPile - 您对EOL不成问题是正确的。我没有注意到这两个FOR/F循环都受到保护,第一个是行号,第二个是#L。我从答案中删除了我的笔记。 – dbenham

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 
+0

我将调用更改为'call:readfile insert%sourcefile%',然后在findstr中将%1更改为%2。再次,同样的问题 - 读取和输出很好......但不会将其重新发回顶部。 – TurdPile

+0

你能看到'echo%insert%'消息吗? – Endoro

+0

它是空白的。 “ECHO关闭” – TurdPile

相关问题