The Will Will Web

記載著 Will 在網路世界的學習心得與技術分享

如何利用批次檔(Batch)讀取指令執行的結果或文字檔案內容

最近從 Visual Studio 2010 的 建置部署套件 功能自動產生的網站安裝批次檔中學到一個批次檔的使用技巧,他可以透過批次檔直接讀取機碼(Registry)的資訊並擷取出執行檔所在路徑,這樣一來就不用將執行檔所在的路徑寫死在批次檔裡,是非常彈性的一種方法,藉此也剛好把批次檔的 FOR 語法的使用方式給釐清一番,這樣一來以後要透過批次檔讀取或解析文字檔就更方便了。

我們先來看看這段批次檔的內容,並解釋各參數的用法,不過這種語法有點學習門檻,一定要多加思考才能融會貫通:

注意:在批次檔中要寫 %i 變數必須要寫成 %%i 才行,如果直接在指令列模式執行時可直接輸入 %i

 alt

  1. /F 代表要 FOR 迴圈會對傳入的字串進行解析(parsing)
  2. "……" 代表「選項設定」,代表 FOR 迴圈應該如何解析傳入的字串,有以下幾種選項:
    1. eol=c 用來決定斷行符號,預設為 \n,但可換成其他字元(其中 c 只能是一個字元)
      : c 為一個字元
    2. skip=n 用來決定要先跳過幾層迴圈(也就是跳過前面幾行的意思)
      : n 為數字
    3. delims=xxx 用來決定欄位的分隔字元,預設為空白TAB符號,並可自訂多個字元
      : xxx 代表多個字元,如果要同時設定小數點 (.) 與逗號 (,) 就要輸入 delims=.,
    4. 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 變數裡
    5. usebackq 用來設定上圖編號4的語法,主要是用在執行的指令中需要包含雙引號(")的情況下,例如 for /F "usebackq" %i IN (`dir /b "C:\Program Files"`) DO @echo %i
  3. %i 代表第一個解析出來的字串的參數代號,第一個為 %i 第二個為 %j 並依照英文字母類推
  4. 小括弧裡面的就是從各管道取得的文字內容,可以讀取的內容包括三種:
    1. 讀取文字檔的內容
      for /F %i IN (sample.txt) DO echo %i
    2. 字串值
      for /F %i IN ("a b c") DO echo %i
    3. 指令執行結果
      for /F %i IN ('dir /b') DO echo %i

上面的第4點當 usebackq 有被設定的情況下會有不同的行為出現:

  1. 讀取文字檔的內容 (與上述一樣)
    for /F "usebackq" %i IN (sample.txt) DO echo %i
    for /F "usebackq" %i IN ("C:\My Folder\sample.txt") DO echo %i
  2. 字串值
    for /F "usebackq" %i IN ('a b c') DO echo %i
  3. 指令執行結果
    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 的 建置部署套件 功能自動產生的網站安裝批次檔了,以下是這段批次檔的內容 (點圖可放大顯示)

alt

先看看執行 reg 指令的輸出為何:

alt

這段指令一共輸出的四行文字,第一行與最後一行都是空白,而這時我們要取得的資料是 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 /? 即可取得這些特殊變數的說明:

alt

然而 %~dpj 會自動將 %j 展開成一個完整路徑,但如果路徑本身就是「絕對路徑」的話就會保留原本的字串,而該判斷是就是利用這個特點判斷是否比對到 MSDeploy 的安裝路徑。

相關連結