解決set /p yn= 接受鍵盤輸入導致ECHO 處於關閉狀態的問題


今天寫了一個自動更新程序的批處理腳本,但是有個變量一直賦值有問題。弄了一個下午終於找到原因及解決方法:

----轉載要說明來自:博客園--邦邦醬好 哦

 

有問題的代碼如下:

@echo off
echo.
set  choice=1
::::::::::::::::::::::::::::::::::::::::::::::
:::::::::::::::程序包上傳FTP::::::::::::::::::
::::::::::::::::::::::::::::::::::::::::::::::
if "%choice%"=="1" (
    echo 請確認你已經把程序包放到本地指定目錄下(y/n):
    set /p yn=
    echo %yn%
    if /i "%yn%"=="n" (
        set yn=""
        goto end
    )
    echo 開始上傳本地最新的程序包到服務器上...
    echo 上傳完畢
)

:end
set choice=
echo 腳本終止!

連續運行4次,中間有2次說“ECHO處於關閉狀態”,然后程序就判斷失敗了,這是為什么呢?

多次試驗發現,如果語句set /p yn=   是在if語句外部,就不會發生這樣的問題。

 

解決代碼:

增加了setlocal enabledelayedexpansion,再改%yn%為!yn!。

@echo off&setlocal enabledelayedexpansion 

echo.
set choice=1
::::::::::::::::::::::::::::::::::::::::::::::
:::::::::::::::程序包上傳FTP::::::::::::::::::
::::::::::::::::::::::::::::::::::::::::::::::
if "%choice%"=="1" (
    echo 請確認你已經把程序包放到本地指定目錄下(y/n):
    set /p yn=
    echo !yn!
    if /i "!yn!"=="n" (
        set yn=
        goto end
    )
    echo 開始上傳本地最新的程序包到服務器上...
    ::call Upload_Ftp.bat
    echo 上傳完畢
)

:end
echo 腳本終止!

 

查了一個下午,發現原因如下:

批處理有一種機制是變量延遲,比如

@echo off
set a=4
set a=5&echo %a%
pause 

打印的結果會是a=4,而不是a=5,因為在讀取了一條完整的語句(set a=4)之后,不立即對該行的變量賦值,而會在某個單條語句(set a=5&echo %a%)執行之前再進行賦值操作。也就是說“延遲”了對變量的賦值。

在cmd執行命令前會對腳本進行預處理,其中有一個過程是變量識別過程,在這個過程中,如果有兩個%括起來的如%value%類似這樣的變量,就會對其進行識別,並且查找這個變量對應的值,再而將值替換掉這個變量,這個替換值的過程,就叫做變量擴展,然后再執行命令。一般是對靜態變量進行值的替換。

setlocal enabledelayedexpansion 就是延遲本地環境變量擴展,在cmd執行中,發生動態的一種情況是在 for語句,if語句中進行變量賦值,在動態變量賦值過程中,如果不主動開啟延遲本地環境變量擴展,是不會對變量進行預處理的。

在上文第一段代碼中,由於在語句(if /i "!yn!"=="n")之前沒有對yn變量進行賦值,所以得到“ECHO處於關閉狀態”的結果。

比如上方第三段代碼,如果啟動了變量延遲並把set a=5&echo%a%改為set a=5&echo!a!,所以批處理能夠感知到動態變化,即不是先給該行變量賦值,而是在運行過程中給變量賦值,因此此時a的值就是5了。

所以我們就要在第一段代碼中加入setlocal enabledelayedexpansion語句,開啟延遲本地環境變量擴展,使得yn變量在if的動態賦值過程中能夠被賦值。

同時注意開啟延遲本地環境變量擴展后,變量需要用!!進行引用。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM