先來說說變量延遲擴展吧。當然,放狗一搜,就能看到滿天飛的關於變量延遲擴展的文章,所以,我這里就簡單介紹一下。先來看一段批處理:
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的值。。。
這么多巧合在一起,誰能不蛋疼。。。