Batch入門教程(2)

weixin_34253539發表於2019-02-17

在本次釋出內容中,我們來了解第一大概念:變數。

變數

變數(Variable),在初中對函式的學習中我們可能接觸到了這個名詞,當然,如果您還沒有接觸到也沒有關係,您只需要將它理解為“一種可以改變的值”即可。在計算機中,變數的含義會更加清晰,因為它的確是可以變的。

我們如果提到變數,就必定會談到賦值(Assignment)。這個賦值並不是代數中的賦值(名詞),而是一個動賓短語。賦,即賦予,給予,這個詞的意思很明顯了,就是給予一個值。給予誰值呢?我們就要談到變數名(Name)了。變數名一般是可以隨便取的,但是如果我們想要更好地去分辨,我們最好取一些有意義的名字。

set

set是變數操作最基本的指令,它能夠指定一個變數名並給它賦值。下面是一個常見的變數賦值表示式:

set a=1

其中,set為變數操作指令,它是不可缺少的。a是變數名,它的值則是=後的1。那麼,=是等號嗎?不是。在計算機領域,=從來沒有等號的意思,它被稱為賦值運算子(Assignment Operator),只要看到它,就代表著左側與右側相等,但是它並不表示相等關係。

也就是說,如果我們要表達“a 與 1 相等”,那麼我們需要的是a==1而不是 a=1。假設此時a的值為hello,那麼我們若執行:

set a=1

此時a的值會被徹底改變,變成1。也就是說,a=x任何時候都成立,因為它是用來改變左側變數名所對應的值的,而a==x僅在a真正與x相等時成立。

經過一系列的糾結和解釋,我們最終得到了一個名為a的變數,它的值為1。那麼這個時候我們就要想辦法來使用它。能不能與之前的echo結合起來呢?

set a=1

echo ****%a%

得到1。是可以的。在Batch中,您可以用%變數名%的形式來表示一個變數,並且在任何地方都可以用,比如:

set a=****set

set b=a

set ****c=^=

set d=1

set e=****%a% %b%%c%%d%

%e%

echo ****%a%

pause

exit

這個突如其來的奇怪程式也許非常難懂。接下來我們慢慢分析。

首先我們可以看到,我們定義了5個變數,分別叫做a, b, c, d, e。那麼您能說出它們的值是多少嗎?我相信答案是肯定的,除了c和e。

a的值為set,b的值為a,c的值為=,d的值為1。那麼,如果我們一個一個地echo它們呢?

echo ****%a%

echo ****%b%

echo ****%c%

echo ****%d%

pause

exit

我們得到的結果將是這樣的:

2478619-86ddcb8dc527e7e1
image

這看起來就像是一個指令:

set a=1

這樣您也許可以猜到e的值是什麼了。沒錯,e的值就是a, b, c, d的組合。可以注意到,%a%右邊有一個空格,其它的都是相連的,這樣組合起來也是不會變的。那麼把

%a% %b%%c%%d%

組合起來,我們就得到了:

set a=1

然後下面有一個單行,寫著:

%e%

這樣,在e的值被賦為set a=1後,再把%e% 當作指令執行,我們就相當於是執行了指令:

set a=1

隨後再echo出a的值,我們得到的是1。

2478619-d0e75450b4b83d41
image

轉義字元

為什麼%c%的值是=而不是^=?

首先我們觀察:

set ****c=^=

在這裡,如果我們去掉了中間的^,那麼這就是一個錯誤的指令,因為==會被識別成判斷是否相等的運算子,而右邊又是空的,更何況set沒有這種用法。

set**** c==

所以我們需要讓cmd知道我們是想讓c等於=(等於等於)。於是^的用處有了。它叫做轉義符(Escape Character),用來把原本有特殊含義的符號給轉義成一般的字元。

轉義符的作用很多,您能想到嗎?

如果我們想要輸出一句話,這句話裡包含%a%,但是我們並不想要輸出a的值,而僅僅是輸出兩個百分號和一個a,怎麼辦?轉義符的用處有了。我們可以這樣寫:

echo ****%%a****%%

這裡我們又用到了一個轉義符,它叫做“雙百分號”,但它只能在使用變數轉義的時候起作用。因而:

set**** c=^=

set**** c=****%%=****%%

不相等。

^轉義符的效用是它後面的1個字元,%%轉義符用來代表一個正常沒有特殊含義的%。使用%%a%%,我們得到的結果就不是a的值了。我們看一個示例:

set**** a=****1

echo ****%a%

echo ****%%a****%%

這樣,我們得到的結果是:

2478619-cbd1d0941c6d1034
image

set /p

set指令有非常多的引數。在本教程中介紹/p和/a兩種。首先,set /p屬於暫留性指令中的一種,也是使用者輸入的第二種途徑。如果您想要讓使用者自己來定義變數的值,您將需要用到/p。

set**** /p a=

含/p引數的set指令,賦值運算子右側無論是什麼,都不會影響到它的值。若我們單單執行set /p a=,我們將得到:

2478619-619ef74877973932
image

這是一個輸入空框,我們可以隨意在這裡輸入東西。例如,我們輸入 123456,那麼什麼也不會發生:

2478619-073e34a98b3dcee1
image

但是如果此時我們調出%a%的值,效果就出現了:

2478619-712d98dc222906e5
image

也就是說,我們輸入的任何東西都已經被賦入了變數a裡。/p引數的用處就在如此。

但是,每一次都是這個輸入空框,使用者根本不知道輸入什麼。這樣,我們就可以再賦值運算子右側加上提示文字,來提示使用者這是在輸入什麼。執行如下程式:

2478619-db2cacc4ae0eceac
image

其中,this is my passwd是筆者手動輸入的部分。

那麼,我們結合先前將變數直接當作指令執行的方式,來製造一個假的cmd控制檯:

2478619-626f084b0ad50785
image

這時,我們輸入的值會直接被賦入%command%內,緊接下一行就是直接把變數的值當作指令來處理。也就是說,我們輸入一條指令,就會被直接當作指令來處理,從而實現假控制檯的效果。

利用這條思路,我們就可以自定義我們自己的控制檯了。當然這是後續的內容。

set /p <

多了一個<,意義就完全不一樣了。準確來說,這種用法是建立在檔案重定向運算子<上的。它的具體用法:

set**** /p a=<****1****.txt

左側沒有多大的區別,仍然是變數名,但是右側則是一個<加上一個檔案。嚴格來講,這個檔案只能是純文字檔案(副檔名隨意,只要不是二進位制即可)。這條指令的意思是從1.txt讀取第一行的所有內容並賦值到%a% 中。

我們不妨直接做個實驗:

2478619-e396f735ebd584ee
image

這樣,從檔案讀取內容也成功了。但是如果有多行文字呢?出於侷限性,這個方法只能讀取第一行的內容。在後面的學習中,我們會介紹如何讀取全部內容,以及如何選擇性地讀取指定行的內容。

set /a

指定/a引數可以進行數學運算操作。如果set指令擁有/a引數,那麼它的賦值運算子後面的變數不需要帶上百分號。

例如:

2478619-fa2ed08cdedf9571
image

但是前提是賦值運算子後的變數****必須為數字。因為/a是專為數學運算而設計的,所以這樣能夠讓計算寫作時更加快速。

一個簡單的加減乘除程式就可以通過引數/a來實現:

2478619-d7e642f787391ba0
image

這代表著在/a引數的前提下,賦值運算子後將可以直接寫四則運算子號。但是這遠遠不夠。因為批處理的侷限性,目前是無法計算超過32位的數字以及任何浮點數的(所以不建議用批處理計算除法)。不過,這樣就相當於是實現了計算器的核心功能。

至此,set介紹得就差不多了。接下來我們瞭解一下環境變數。

環境變數

環境變數(Environment Variable),是指系統已經預先配置好的父程式環境預設設定。簡要來講,就是一些包含您計算機的基本資訊的變數,雖然說叫做“變數”,但是實際上如果您的系統沒有從底層上發生改變,這些變數的值是不會改變的。

環境變數在批處理的作用非常巨大,可以節省我們編寫程式碼的時間,也能讓我們的程式碼更加適配其它人的電腦。

我們舉個例子,眾所周知很多人的Windows系統是安裝在碟符為C:的儲存空間的,因此如果我們在批處理內要對系統盤內的項進行操作,我們必定需要寫路徑。例如,我們要用上文中提到的set /p指令來讀取位於系統盤根目錄的1.txt,那麼怎麼做?(忽略許可權)

set**** /p content=<C:*1****.txt*

一般我們的思路當然就會是這樣的了,但是,您有沒有思考過,萬一真的有人系統盤不在C盤呢?(實際上這種情況非常普遍)這條指令豈不是失去意義了?這個時候,環境變數就發揮作用了。環境變數可以根據不同的電腦而改變,這就是它“變”的地方。

例如,在Windows中有一個環境變數,叫作%SYSTEMDRIVE%(環境變數不區分大小寫),它的字面意思是系統碟符(System Drive Volume),這也是它所代表的。那麼我們可以直接在echo指令中輸出它,因為它在系統安裝的時候就被定義了。

2478619-51e3682c14af2b43
image

我們得到的是C:,這正是我們系統盤的碟符。

而如果某人的電腦系統盤是E:,那麼這個變數的值就會等於E:。利用這個原理,我們就可以適配所有的電腦了,於是把我們的指令修改成:

set****/p content=<****%SYSTEMDRIVE%*****1****.txt*

這樣,這條指令就有了萬能性。

環境變數的使用方法基本上就是這樣,接下來我們列出一些常用的環境變數:

2478619-f9de119e56a78f07
image
2478619-248d77b6bf37f9dd
image

變數擷取與替換

如果我們希望將一個變數分段,只取其中一部分內容,在Batch中是有方法的。

set**** a=****1234567890

echo ****%a:~0,1%

上面的執行結果是1。看吧,這是一個您不認識的變數寫法。:~0,1就是變數控制符。一般地,在Batch中,我們對變數擷取有以下原則:

%操作變數名:~始, 終%

其中,操作變數名很好理解,這是我們要採取擷取工作的變數。例如,我們要擷取變數a,那麼操作變數名就是a。始(from Index),指定從哪一(Index)開始擷取,(to Index)指定擷取到的位。

在計算機中,位是從0開始的。也就是說,我們日常生活中所表示的1,在這裡就是0。觀察以下資料:

1234567890

請問這組資料中的第一個數字是什麼?是1。但是,如果我們要在計算機內表示的話,我們要說它在第0位。以此類推,如果我們要擷取變數的前8位,那麼我們應當寫成:

%a:~0,8%

這行程式碼代表擷取變數a的第一位至第八位。如果我們仿照上例執行:

set**** a=****1234567890

echo ****%a:~0,8%

我們將得到12345678。這種擷取也適用於非0開頭。需要注意的是,開頭的位必須與我們現實生活中所數的位數少1。例如:

set**** a=你好啊

echo ****%a:~1,1%

輸出的結果是好。這行程式碼代表從第2位開始,擷取1個字元。那麼我們就直接擷取了第2位本身。如果我們將終改為2,我們得到的結果是 好啊,即從第2位開始,擷取了2位。

請您參考如下例子來好好了解一下變數擷取:

2478619-bcdbcfcaf288ef73
image

我們同樣可以反過來,從相反方向擷取。例如:

set**** a=****3.14

echo ****%a:~-1%

這種用法裡沒有始和終的區分。以上例子代表擷取a的倒數第一位,我們得到的結果是4。如果我們使用echo %a:~-2%,那麼我們擷取的是倒數的兩位,結果是14。以此類推,當我們使用echo %a:~-n% 的時候,實際上是擷取了這個資料的倒數n位(即從倒數第1位一直擷取到倒數第n位)。

此外我們還可以結合起來用:

set**** a=****3.14

echo ****%a:~0,-1%

我們得到的結果是3.1。這行指令代表擷取從正數第一位一直到倒數第一位之前的那一位的資料。以此類推,當我們使用echo %a:~b,-c%的時候,實際上是擷取了這個變數從正數第a+1位到倒數第|c|+1位的資料。

至於變數替換,相對於變數擷取,比較簡單。

set**** a=我好!

echo ****%a:我=你%

我們得到的結果是你好!。也就是說,%a:A=B即將變數內任何與A完全匹配的內容全部替換成B。