Scripting Guy 為您解答問題

Hey, Scripting Guy!

歡迎使用 TechNet 專欄,Microsoft Scripting Guy 會在此為您解答有關系統管理指令碼的常見問題。您有關於系統管理指令碼方面的問題嗎?請將電子郵件傳送到 scripter@microsoft.com。我們無法保證能夠逐一回答每個問題,不過我們會盡力而為。

資源

如何讀取文字檔的內容,然後將其內容宣告成變數?

Hey, Scripting Guy! Question

嗨,Scripting Guy!如何讀取文字檔的內容,然後將這些內容宣告成變數?


        -- TC

Hey, Scripting Guy! Answer

TC,您好。開始之前,我們想確定一下您是否真的要問我們這個問題?我們相信您是認真的,但是由於最近發生了一些事,所以我們不太敢確定。

例如,到目前為止,每個人都聽說過 Scripting Guy Jean Ross 南下聖地牙哥參加 MMS 會議,但是當她回來時,頭上卻多了手術缝合的痕跡 (英文)

請注意:事情是這樣的,當 Jean 在聖地牙哥動物園裡面悠閒地散步時,她注意到一群正在遠足的幼稚園學生不小心闖入灰熊的圍欄。此時,Jean 完全不顧自身的安危,跳過柵欄、擊退熊群,並將每個孩子帶到安全之地。在奮戰期間,其中一隻灰熊打到 Jean 的頭,結果造成慘不忍睹的傷口。當孩子們都平安之後,Jean -- 果然是她的本色 -- 返回圍欄、對灰熊的爪子施以急救處理,然後才到醫院處理她的傷口。

但是,下個部分就有點詭異 (順道一提,對於 Jean 而言,在她的頭上施行縫合手術並非奇怪的部分)。隔天,我們的 Scripting 英雄便向保險公司詢問有關理賠的問題。但是,保險公司卻告訴她,他們並沒有她在聖地牙哥就診的記錄。很顯然,她在聖地牙哥時,並沒有縫合她的頭!

更奇怪的是,上個禮拜,當撰寫本專欄的 Scripting Guy 電腦壞掉時,他正在撰寫這則專欄。當他嘗試重新啟動電腦 (而且他試了很多次) 時,永遠收到同一則訊息:非系統或磁碟錯誤。當時,他打算進入 BIOS,認為應該要執行硬碟診斷測試。然後發生什麼事呢?什麼事都沒有:那個選項呈現灰色。很顯然,電腦並沒有硬碟。

當時,撰寫本專欄的 Scripting Guy 做了一件 Scripting Guy 在緊急關頭時都會做的事:他跑去吃午餐了。當他回來時,他決定再重新啟動一次電腦,反正死馬當活馬醫。不用說,電腦完全正常地開機了。接著他一次又一次地重新啟動。還是沒有任何問題。他進入 BIOS 並發現電腦確實具有硬碟。除此之外,電腦順利地通過了所有診斷檢查。很顯然,他的電腦最後沒有壞掉。

非常奇怪吧。

反正呢,TC,我們不能確定您是不是真的要問如何讀取文字檔的各行,然後將該項資訊宣告成變數。不過,如果您真的要問如何讀取文字檔的各行,然後將該項資訊宣告成變數,答案如下。

當然,除非最後我們沒有回答問題,那就另當別論了。但是,不妨試試下列指令碼,然後看看有什麼結果。

Script Center
Const ForReading = 1

Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objFile = objFSO.OpenTextFile("C:\Scripts\Test.txt", ForReading)

Do Until objFile.AtEndOfStream
    strLine = objFile.ReadLine
    Execute strLine
Loop

objFile.Close

Wscript.Echo strFirstName
Wscript.Echo strLastName

好,假設我們瞭解您的問題 (也就是那個您有問或沒有問的問題),您有一個含有類似下面各行的文字檔:

strFirstName = "Ken"
strLastName = "Myer"

如您所見,每一行都非常像將值指派給變數的程式碼行。事實上,如果您原封不動地將這些行輸入指令碼,最後就會得到名為 strFirstName 的變數 (含有 Ken 的值) 和名為 strLastName 的變數 (含有 Myer 的值)。當然,您不會想要原封不動地將這些行輸入指令碼。不過,您想要從文字檔讀取這些行,然後執行每一行,就如同您已經將它輸入指令碼一樣。換言之,即使您沒有實際地輸入這兩行程式碼,您仍希望指令碼會運作,如同您已輸入這兩行程式碼一樣。

看吧?我們告訴過您,每件事都變得很奇怪!

那麼,我們要如何完成上述作業呢 (無論如何)?首先,我們要定義一個名為 ForReading 的常數並將其值設定為 1。這是我們在開啟文字檔時所需的常數。在常數定義完成之後,我們接著要建立 Scripting.FileSystemObject 物件的執行個體,然後開啟檔案 C:\Scripts\Test.txt:

Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objFile = objFSO.OpenTextFile("C:\Scripts\Test.txt", ForReading)

現在精彩的部分來了。接下來,我們必須逐行讀取文字檔,然後執行文字檔的每一行,就如同它是我們輸入指令碼的程式碼行一樣(為什麼我們要一直使用「執行」這個動詞呢?您稍後就會瞭解了)。為了這樣做,我們首先要設定一個 Do Until 迴圈,而該迴圈設計成在我們到達文字檔的結尾之前 (也就是說,在檔案的 AtEndOfStream 屬性為 True 之前) 執行。在該迴圈內部,我們要使用 ReadLine 方法,從文字檔的第一行開始讀取,然後將該值儲存在名為 strLine 的變數中:

strLine = objFile.Readline

都了解了嗎?這僅表示,strLine 等於下面這行:

strFirstName = "Ken"

這對我們有用嗎?絕對有。為了建立名為 strFirstName 的變數 (含有 Ken 的值),接下來我們必須呼叫 Execute 陳述式,後面接著要執行的值:

Execute strLine

Execute 陳述式是 VBScript 中鮮為人知但卻很重要的功能。此外,這個陳述式可讓您執行字串值 (或變數),就如同您已經該值輸入指令碼當做程式碼行一樣。有點困惑嗎?沒關係。請看一下這個指令碼範例:

strMessage = "Hi"
strCode = "Msgbox strMessage"
Execute strCode

在此,我們將文字值 Hi 儲存到名為 strMessage 的變數中。然後,我們將下列值指派給名為 strCode 的變數:

Msgbox strMessage

您說的沒錯,這確實很像在訊息方塊中顯示 strMessage 值的程式碼行。而且,這樣做的原因是:它的確是在訊息方塊中顯示 strMessage 值的程式碼行。這就是完整的想法。現在,為了執行該程式碼行 (也就是說,為了顯示訊息方塊),我們接下來必須呼叫 Execute 陳述式,後面接著想要執行的字串值 (在此情況下,就是變數 strCode)。

只要您自己試試看,就知道我們的意思了。

無論如何,當我們呼叫 Execute 陳述式時,結果就會執行這個值:

strFirstName = "Ken"

而且,您知道嗎?這樣就會建立名為 strFirstName 的變數,並將值 Ken 指派給它。接著我們再執行迴圈,並且對文字檔中的下一行重複此程序。

不可否認,這聽起來有點瘋狂。但是,當我們回應 strFirstName 和 strLastName 的值時,看看得到的結果:

Ken
Myer

顯然,strFirstName 和 strLastName 都是有效的變數。那麼,您認為如何指派個別的值給它們呢?沒錯:從文字檔中找到的資訊。怎樣,很酷吧!

不可否認,我們不確定您必須從文字檔讀取程式碼行,然後將這些程式碼行宣告成變數的頻率有多高。不過,有時候 Execute 陳述式真的很實用。哪些時候呢?呃,至少有一個例子,請參閱「2007 冬季指令碼比賽」的這個比賽項目 (英文)

總之,希望上述說明能回答您的問題,TC。如果結果顯示您沒有真的我們問題,也沒關係:反正最近發生了一點事,所以我們也不確定是否有回答問題。我們有沒有提過兩位報名參加 TechEd 2007 (英文) 的 Scripting Guy 已收到確認註冊的電子郵件,但是幾天後卻又收到通知他們尚未註冊的電子郵件呢?畢竟,他們最後還是收到確實註冊的通知了。好吧,當我沒說。很可能這件事也完全沒發生過。反正,我們將在 TechEd 2007 與各位讀者見面。

當然,假設確實有 TechEd 2007 這種會議的話。