1. 程式人生 > >批處理——感嘆號和變數延遲擴充套件

批處理——感嘆號和變數延遲擴充套件

 

先來說說變數延遲擴充套件吧。當然,放狗一搜,就能看到滿天飛的關於變數延遲擴充套件的文章,所以,我這裡就簡單介紹一下。先來看一段批處理:

set str=test

if %str%==test (
    set str=another test
    echo %str%
)

上面的程式碼段極其簡單,給str賦值,判斷其值是否為test,如果是,重新賦值為another test,再顯示str的值。

作為正常人的思維,這裡顯示的肯定是another test了,但其實不是,其顯示的仍然是test,這是為什麼?因為:windows在解釋執行此程式碼段時,在遇到if語句後的括號後,只把它當一條語句處理而不是兩條語句,所以,在第二條語句中的%str%會被替換成它目前的值test,上面的程式碼相當於下面的程式碼的效果:

set str=test

if %str%==test (
    set str=another test
    echo test    ::注意這裡
)

所以,輸出自然是test了。

這樣程式設計的靈活性就大大降低了,於是,M$就想了一個workground的方法,那就是變數延遲,很簡單,看如下程式碼:

@echo off
setlocal enabledelayedexpansion    ::注意這裡

set str=test

if %str%==test (
    set str=another test
    echo !str!      ::注意這裡
    echo %str%  ::區別
)

現在會輸出什麼呢?試一下就知道,第一行輸出another test,第二行輸出test。

現在解釋一下,setlocal enabledelayedexpansion用於開啟變數延遲,這是告訴直譯器,在遇到複合語句的時候,不要將其作為一條語句同時處理,而仍然一條一條地去解釋。但是這時必須用!str!來引用變數,如果仍然用%str%引用是不起作用的。

好了,變數延遲擴充套件解釋完了,至少這就是我知道的變數延遲擴充套件。

=========================== 我是自豪的分割線,如果你只想知道變數延遲擴充套件是怎麼回事,看到這裡就OK了 ===========================

今天變數延遲擴充套件和感嘆號讓我蛋疼了半天,所以現在也要來扯扯它們的蛋。

試試以下程式碼段:

@echo off

setlocal enabledelayedexpansion

set str=test!!!

echo %str%

開啟變數延遲,給str賦值,輸出str,於是,輸出自然是test!!!了。但其實,windows告訴我們,又錯了,輸出是test,感嘆號被windows吃了。

當然如果註釋掉開啟變數延遲那一行,這幾行是可以正常工作的,所以說是開啟變數延遲影響了我們正常的工作,但我至今還沒搞清楚為什麼會這樣,這隻有M$知道。

於是,關閉變數延遲吧,可是程式又需要使用變數延遲來實現一些邏輯,怎麼辦?兩個辦法:

1.暫時關閉變數延遲:

@echo off

setlocal enabledelayedexpansion

:: do something here

setlocal disabledelayedexpansion    ::關閉變數延遲

set str=test!!!

echo %str%

setlocal enabledelayedexpansion

:: continue...

在需要處理感嘆號的地方,暫時關閉變數延遲,處理完後再開啟。這時能正常輸出感嘆號。

2.在開啟變數延遲之前set:

@echo off

set str=test!!!

setlocal enabledelayedexpansion

echo !str!    ::注意這裡

在開啟變數延遲之前設定好變數,但是要注意,在使用變數的時候,需要使用感嘆號引用。這時感嘆號也可以正常輸出。

最後貼一段為什麼讓我蛋疼的程式碼(變數延遲自然是開啟的):

set server=%~1
set username=%~2
set password=%~3
echo %date%, %time% [INFO]   Report server address: [%server%], username: [%username%], password: [*******]

rs.exe -i "PublishReports.rss" -s "%server%" -u "%username%" -p "%password%" -l 600

為了不回顯password,我輸出了一大串*。在我機器上測試時,我的password字元都很常規,所以通過。但是,QA的password裡面有感嘆號。。。

關鍵的是,這裡呼叫的是M$的Report Server的rs.exe來上傳模板,它丟擲一個Could not connect的exception,於是,我自然地想到是report server的service出了問題,但查了好久也沒發現report server有什麼問題。。。誰TMD會想到是別人的password裡有感嘆號,誰TMD又會想到是跟所謂延遲變數的衝突導致的,更有誰會想到,我自己自作聰明地為了不顯示password而顯示出了一大串hard code的星號導致看不到password的值。。。