如何利用批次檔(Batch)讀取指令執行的結果或文字檔案內容
最近從 Visual Studio 2010 的 建置部署套件 功能自動產生的網站安裝批次檔中學到一個批次檔的使用技巧,他可以透過批次檔直接讀取機碼(Registry)的資訊並擷取出執行檔所在路徑,這樣一來就不用將執行檔所在的路徑寫死在批次檔裡,是非常彈性的一種方法,藉此也剛好把批次檔的 FOR 語法的使用方式給釐清一番,這樣一來以後要透過批次檔讀取或解析文字檔就更方便了。
我們先來看看這段批次檔的內容,並解釋各參數的用法,不過這種語法有點學習門檻,一定要多加思考才能融會貫通:
注意:在批次檔中要寫 %i 變數必須要寫成 %%i 才行,如果直接在指令列模式執行時可直接輸入%i
- /F 代表要 FOR 迴圈會對傳入的字串進行解析(parsing)
- "……" 代表「選項設定」,代表 FOR 迴圈應該如何解析傳入的字串,有以下幾種選項:
- eol=c 用來決定斷行符號,預設為 \n,但可換成其他字元(其中 c 只能是一個字元)
註: c 為一個字元 - skip=n 用來決定要先跳過幾層迴圈(也就是跳過前面幾行的意思)
註: n 為數字 - delims=xxx 用來決定欄位的分隔字元,預設為空白與TAB符號,並可自訂多個字元
註: xxx 代表多個字元,如果要同時設定小數點 (.) 與逗號 (,) 就要輸入 delims=., - tokens=x,y,m-n 用來決定一次要取出幾個欄位,第一個欄位會存放在第一個自動變數,第二個欄位會存放在第二個自動變數裡,依此類推。如果你設定第一個變數為 %i 那麼如果設定為 tokens=1,2 就代表你會得到一個 %i 與一個 %j 變數值,分別代表比對到的第1與第2個欄位。這裡有個特殊的情況是使用星號 ( * ),如果你設定為 tokens=1*就代表你會得到一個 %i 變數值,以及一個 %j 變數值,但是 %j 變數值就不會再進行解析,而是將剩餘的文字全部都塞進 %j 變數值裡!
註: x, x, m, n 都為數字,只是 m-n 是一種特別的表示法,代表一個解析欄位的範圍。例如 tokens=2-4 就代表取得三個變數,取得第2、第3與第4個欄位的值並塞入 %i $j %k變數裡 - usebackq 用來設定上圖編號4的語法,主要是用在執行的指令中需要包含雙引號(")的情況下,例如 for /F "usebackq" %i IN (`dir /b "C:\Program Files"`) DO @echo %i
- eol=c 用來決定斷行符號,預設為 \n,但可換成其他字元(其中 c 只能是一個字元)
- %i 代表第一個解析出來的字串的參數代號,第一個為 %i 第二個為 %j 並依照英文字母類推
- 小括弧裡面的就是從各管道取得的文字內容,可以讀取的內容包括三種:
- 讀取文字檔的內容
for /F %i IN (sample.txt) DO echo %i - 字串值
for /F %i IN ("a b c") DO echo %i - 指令執行結果
for /F %i IN ('dir /b') DO echo %i
- 讀取文字檔的內容
上面的第4點當 usebackq 有被設定的情況下會有不同的行為出現:
- 讀取文字檔的內容 (與上述一樣)
for /F "usebackq" %i IN (sample.txt) DO echo %i
for /F "usebackq" %i IN ("C:\My Folder\sample.txt") DO echo %i - 字串值
for /F "usebackq" %i IN ('a b c') DO echo %i - 指令執行結果
for /F "usebackq" %i IN (`dir /b`) DO echo %i
for /F "usebackq" %i IN (`dir /b "C:\Program Files"`) DO @echo %i
知道 FOR 語法如何解析文字內容後,我們就可以來分析從 Visual Studio 2010 的 建置部署套件 功能自動產生的網站安裝批次檔了,以下是這段批次檔的內容 (點圖可放大顯示)
先看看執行 reg 指令的輸出為何:
這段指令一共輸出的四行文字,第一行與最後一行都是空白,而這時我們要取得的資料是 MSDeploy 的安裝路徑,所以我們要抓取畫面上的 C:\Program Files\IIS\Microsoft Web Deploy\文字。
而在 FOR 語法裡我們有用到兩個選項設定:
- usebackq 用來讓指定輸入時可以包含雙引號(")
- tokens=2* 用來決從第2個欄位開始取資料,訂且在第二個自動變數填入這一行剩下的所有資料,也就是 %i 變數值會是第二個欄位,而 %j 變數值會是第三個欄位以後的所有文字
預設解析會以空白字元與 TAB 符號作為分隔字元,而我們要取得的 tokens 是從第二個欄位開始,所以當比對的文字連第二個欄位都沒有時,就會自動忽略,因此雖然我們有四行文字,但第一行與最後一行都會跳過不處理。
所以我們的迴圈會執行兩遍:
第 1 遍,在迴圈裡會取得的變數與值分別是:
- %i = Extensions\MSDeploy\1
- %j = <空白>
第 2 遍,在迴圈裡會取得的變數與值分別是:
- %i = REG_SZ
- %j = C:\Program Files\IIS\Microsoft Web Deploy\
我們也在批次檔中看到一個 IF 判斷式:
if "%%~dpj" == "%%j" (
這個判斷是特別的地方在於 %~dpj 這個特殊變數,我們執行 FOR /? 即可取得這些特殊變數的說明:
然而 %~dpj 會自動將 %j 展開成一個完整路徑,但如果路徑本身就是「絕對路徑」的話就會保留原本的字串,而該判斷是就是利用這個特點判斷是否比對到 MSDeploy 的安裝路徑。
留言列表