2012-11-02 30 views
1

這是我的腳本:如何生存「延遲變量擴充」在DOS批處理腳本

@echo off 
setlocal 

for /f %%i in ('echo aaa/') do set REPO=%%i 
if "%REPO%"=="" (
    echo No input 
) else (
    echo %REPO:~-1% 
    echo %REPO:~0,-1% 
    if %REPO:~-1%==/ set REPO=%REPO:~0,-1% 
    echo %REPO% 
) 

endlocal 

請注意以下幾點:

c:\dev\shunra\GlobalLibrary\Server>c:\Utils\hgbackup.cmd 
/
aaa 
aaa/ 

c:\dev\shunra\GlobalLibrary\Server> 

這是怎麼回事?

編輯

。注意,我分配給回購的東西,評估爲「AAA」,所以我希望它打印「AAA」,而不是「AAA /」。它讓我瘋狂。

EDIT2

顯然,這裏是罪魁禍首(從set命令幫助):

Finally, support for delayed environment variable expansion has been 
added. This support is always disabled by default, but may be 
enabled/disabled via the /V command line switch to CMD.EXE. See CMD /? 

Delayed environment variable expansion is useful for getting around 
the limitations of the current expansion which happens when a line 
of text is read, not when it is executed. The following example 
demonstrates the problem with immediate variable expansion: 

    set VAR=before 
    if "%VAR%" == "before" (
     set VAR=after 
     if "%VAR%" == "after" @echo If you see this, it worked 
    ) 

would never display the message, since the %VAR% in BOTH IF statements 
is substituted when the first IF statement is read, since it logically 
includes the body of the IF, which is a compound statement. So the 
IF inside the compound statement is really comparing "before" with 
"after" which will never be equal. Similarly, the following example 
will not work as expected: 

    set LIST= 
    for %i in (*) do set LIST=%LIST% %i 
    echo %LIST% 

in that it will NOT build up a list of files in the current directory, 
but instead will just set the LIST variable to the last file found. 
Again, this is because the %LIST% is expanded just once when the 
FOR statement is read, and at that time the LIST variable is empty. 
So the actual FOR loop we are executing is: 

    for %i in (*) do set LIST= %i 

which just keeps setting LIST to the last file found. 

Delayed environment variable expansion allows you to use a different 
character (the exclamation mark) to expand environment variables at 
execution time. If delayed variable expansion is enabled, the above 
examples could be written as follows to work as intended: 

    set VAR=before 
    if "%VAR%" == "before" (
     set VAR=after 
     if "!VAR!" == "after" @echo If you see this, it worked 
    ) 

    set LIST= 
    for %i in (*) do set LIST=!LIST! %i 
    echo %LIST% 

但我嘗試使用!標誌,它仍然不適合我的工作。我用屏幕上打印的!或者再次輸入錯誤的結果。

+0

什麼輸出也*你*期待什麼呢?你的批處理腳本應該做什麼? –

+0

看起來沒錯。你打算做什麼? – theglauber

+0

編輯我的帖子。 – mark

回答

3

正如評論和你編輯的問題中所討論的那樣,你需要延遲擴展。

必須先啓用延遲擴展,然後才能使用它。在批處理腳本,您可以使用setlocal enableDelayedExpansion

@echo off 
setlocal enableDelayedExpansion 

for /f %%i in ('echo aaa/') do set REPO=%%i 
if "%REPO%"=="" (
    echo No input 
) else (
    echo %REPO:~-1% 
    echo %REPO:~0,-1% 
    if %REPO:~-1%==/ set REPO=%REPO:~0,-1% 
    echo !REPO! 
) 

endlocal 

編輯

如果IN()子句改變,使得REPO是不確定以上失敗。例如:in (echo.)

它失敗了,因爲整個IF/ELSE結構必須具有有效語法,即使它不會執行ELSE子句。

如果REPO是不確定的,那麼

if %REPO:~-1%==/ set REPO=%REPO:~0,-1% 

擴展到

if ~-1REPO:~0,-1 

這是無效的語法。

該問題再次通過使用延遲擴展來解決。

@echo off 
setlocal enableDelayedExpansion 

for /f %%i in ('echo.') do set REPO=%%i 
if "%REPO%"=="" (
    echo No input 
) else (
    echo %REPO:~-1% 
    echo %REPO:~0,-1% 
    if !REPO:~-1!==/ set REPO=%REPO:~0,-1% 
    echo !REPO! 
) 

endlocal 
+0

幾乎在那裏。它適用於'echo aaa /'和'echo aaa',但不適用於'echo.'。 – mark

+0

@mark - 'echo.'打印一個空行,FOR/F循環總是忽略空行。 – dbenham

+0

它爲什麼重要?如果你在FOR之後立即插入'echo「x%REPO%x」',那麼它會在'echo.'的情況下打印「xx」,這是正確的。那爲什麼IF不起作用?我的意思是你解決了延遲擴展問題,那麼現在是什麼? – mark

0

。注意,我分配給回購的東西,計算結果爲 「AAA」

其實,你有條件分配的東西。您是否測試後續部分是否實際執行(例如,echo If Entered)。

0

這對我的作品(只是從我的整個腳本摘錄)

choice /C 1234567H /M "Select an option or ctrl+C to cancel" 
set _dpi=%ERRORLEVEL% 

if "%_dpi%" == "8" call :helpme && goto menu 

for /F "tokens=%_dpi%,*" %%1 in ("032 060 064 096 0C8 0FA 12C") do set _dpi=%%1 
echo _dpi:%_dpi%: 
相關問題