批處理之坑爹的感嘆號和變量延遲擴展


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

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的值。。。

這么多巧合在一起,誰能不蛋疼。。。


免責聲明!

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



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