2013-08-05 37 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

相關問題