Windows PowerShell提供了豐富的運算子讓我們處理程式裡的各種運算,這裡將分兩篇文章來說明,本文將先說明其中的算術運算及比較運算。<table width="100%" border="0">
<tr>
<td width="50%"><span class="green_13x">● 運算式、運算子、運算元</td></span>
<td width="50%"><span class="green_13x">● 比較運算</td></span>
</tr>
<tr>
<td><span class="green_13x">● 算術運算</td></span>
<td><span class="green_13x">● 結語</td></span>
</tr>
</table>
程式的執行過程充滿了許許多多的運算,在程式裡,我們會將運算的過程寫成運算式,而程式執行運算式便能完成運算。
運算式、運算子、運算元
運算式是由運算元和運算子所構成,運算子是運算式裡參與運算的符號(例如算術運算的+、-、*、/),而運算元則是參與運算的資料,這些資料可以直接以數值表示,也可以是變數、常數,或另一個運算式,有些程式語言甚至允許物件或函式作為運算元。
此外,根據運算子所作用的運算元數量,運算子又可分成一元運算子、二元運算子、三元運算子;例如加法運算需要兩個運算元,因此加法運算子即為二元運算子。
算術運算
Windows PowerShell提供的算術運算子包括了加減乘除四則運算、餘數運算、負號,以及遞增和遞減運算。這些運算子列表如下。
運算子 |
說明 |
簡例 |
+ |
加 |
123 + 456 |
- |
減 |
456–123 |
* |
乘 |
123 * 456 |
/ |
除 |
456 / 123 |
% |
取餘數 |
456 % 123 |
- |
負號(一元運算子) |
-456 |
++ |
遞增(一元運算子) |
$var = 10
$var++ |
-- |
遞減(一元運算子) |
$var = 10
$var-- |
加、減、乘、除、餘數運算以及負號,應該已為一般人熟悉,於此不再贅述,但要提醒的是,加法運算子亦可作為字串連接之用(例如"ab" + "cd"的結果是abcd);此外也應留意參與運算的運算元型別是否一致,及Windows PowerShell會不會逕自對運算元轉換型別。
而關於算術運算子的優先順序,也與你認知的先乘除、後加減相同:負號最高,乘、除、取餘數其次,加、減最低。遞增和遞減運算可能是一般人較為陌生,但如果學過C語言或其家族成員的任何一種語言,對遞增和遞減應該就不至於陌生。遞增和遞減運算每次會讓運算元加1或減1,它們除了是一元運算子(也就是運算時只能有一個運算元),而且只能使用於變數或屬性。Windows PowerShell的遞增和遞減運算子也同C語言,可以前置、也可以後置,例如以下簡單的範例:
# 只能對變數或屬性作用,因此會導致錯誤
PS > 9++
# 先宣告變數$var,並指定其值為10
PS > $var = 10
# 後置遞增,遞增符號放在運算元之後
PS > $var++
# 前置遞增,遞增符號放在運算元之前
PS > ++$var
# 上述不論前置或後置,其寫法都等同於 $var = $var + 1
# 如果是遞減,等同於 $var = $var - 1
# 經過兩次的遞增運算之後,$var的值會是 12
# 如果是兩次遞減,$var的值會是 8 |
上述簡單例子的前置或後置應該不難理解,但如果又搭配其他的算術運算,結果可能會出乎意料,而這應該就是遞增和遞減運算最容易迷惑初接觸者的「特性」,例如以下簡單的範例:
PS > $a = 10
PS > $a++ - 3?? # 結果為 7,$a的值為 11
PS > ++$a - 3?? # 結果為 9,$a的值為 12
PS > $b = 10
PS > $b-- - 3?? # 結果為 7,$a的值為 9
PS > --$b - 3?? # 結果為 5,$a的值為 8 |
各位應該都能理解這個例子$a或$b的值:每次就是加1或減1,但是對運算結果可能有疑惑。其實關鍵就在遞增和遞減運算子前置或後置的差異:如果是後置,會先進行運算式裡其他的運算(也就是10會先減3),再做遞增或遞減運算;但如果是前置,則會先做遞增或遞減運算(也就是11先加1、9先減1),接著才會進行運算式裡其他的運算(因此變成12 - 3以及8 - 3)。
比較運算
比較運算的結果會得到真(True)或偽(False),因此經常用在需要決策的陳述式,例如if或while。但是與一般程式語言不同的是,Windows PowerShell的比較運算子並非常見的代數比較符號,而是英文字的縮寫,因為>或<之類的符號已經用在輸出重導。這些運算子列表如下。
乍看以上表格,你可能會覺得Windows PowerShell的比較運算怎麼這麼複雜!運算子這麼多?這是因為Windows PowerShell的比較運算除了可以比較數值大小,也可以比較字串,而為了要能處理字母大小寫以及忽略大小寫的字串比較,每個比較運算子又衍生出c開頭和i開頭的運算子。
例如等於運算子-eq用在字串比較時,其實就是忽略大小寫的,但Windows PowerShell也另外提供了明確表示忽略大小寫的等於運算子-ieq;也就是說-eq和-ieq在比較字串時,都會忽略字母大小寫,例如會將ABC和abc視為相同。但如果想要比較大小寫的差異,就要使用c開頭的比較運算子,例如用-ceq來比較ABC和abc,就會因為視為不同的字串而得到False。
比較運算的型別轉換
使用Windows PowerShell的比較運算應該留意運算子左右的型別是否一致,不然就應該自行加入型別轉換,或者瞭解Windows PowerShell自動轉換的規則,否則可能得到出乎意料的結果。
若比較運算子兩邊的運算元都是數值,則會根據寬度較大的運算元來擴大另一個運算元的數值寬度,例如一邊是整數、一邊是浮點數,就會先將整數擴大成浮點數,再行比較。將整數擴大成浮點數會加上小數點,並且將小數位數補0,因此678 -lt 678.9,其實是678.0 -lt 678.9(雖然結果相同)。
如果比較運算子兩邊運算元的型別不同,會先依據左邊運算元的型別來轉換右邊運算元的型別,再進行比較運算。例如以下簡單的範例:
# 數值比較,因此會忽略0
PS > 09 -eq 009
True
# 比較運算子兩邊運算元的型別不同,
# 因此會先依據左邊運算元的型別來轉換右邊運算元的
# 型別,再進行比較運算,
# 故而等同於09 -eq 009
PS > 09 -eq "009"
True
# 同上,先依據左邊運算元的型別來轉換右邊運算元的型
# 別再進行比較運算,
# 因此等同於"09" -eq "009"
PS > "09" -eq 009
False
# 比較運算亦可自行型別轉換,
# 轉換之後等同於09 -eq 009
PS > [int] "09" -eq 009 |
比較運算亦可自行加入型別轉換,例如以下簡單的範例:
# 左邊的運算元先轉換成整數型別
# 根據左邊運算元的型別轉換右邊運算元的型別,
# 因此會將678.4四捨五入變成678
# 故而等同於678 -lt 678
PS > [int] "678" -lt "678.4"
False
# 同上,但678.9會進位成679
# 故而等同於678 -lt 679
PS > [int] "678" -lt "678.9"
True
# 左邊的運算元先轉換成倍精度浮點數型別
# 根據左邊運算元的型別轉換右邊運算元的型別,
# 故而等同於678.0 -lt 678.4
PS > [double] "678" -lt "678.4"
True
# 將字串轉換成日期型別再比較
PS > [datetime] "1/1/2007" -gt [datetime] "1/1/2006"
True |
陣列或集合的比較運算
Windows PowerShell的陣列或集合也可以進行比較運算,其運算結果會傳回相符的值,例如以下簡單的範例:
# 左運算元是陣列,此運算會以右運算元搜尋比較此陣列
# 內容,
# 並找出「等於」右運算元的值;
# 結果共有兩個相等,因此列出兩個2。
PS > 2, 3, 4, 2, 3, 4 -eq 2
2
2
# 以右運算元搜尋比較此陣列內容,並找出「不等於」右
# 運算元的值;
# 結果共有四個不相等,因此列出1、3、4、5。
PS > 1, 2, 3, 4 -ne 2
1
3
4
5
# 以右運算元搜尋比較此陣列內容,並找出等於右運算元
# 的值
# 比較時若兩邊的型別不同,就會根據之前所提:
# 先依據左邊運算元的型別來轉換右邊運算元的型別,再
# 進行比較運算
PS > 1, "3", 5, 3 -eq "3"
3
3
# 之所以只有一個3,是因為 "03" 並不等於 "3"
PS > 1, "03", 5, 3 -eq 3
3
# 以下是上例的小變化,請注意右運算元改成 "03",結
# 果也不相同
PS > 1, "03", 5, 3 -eq "03"
03
3 |
上述的比較運算不只能用在等於和不等於,例如以下使用小於的例子,會以右運算元搜尋比較左邊陣列內容,並找出「小於」右運算元的值,因此結果只有1。
PS > 1, "03", 5, 3 -lt "03"
1 |
-contains和-notcontains:陣列或集合的包含運算
陣列或集合的包含運算很類似上述的比較運算,但執行結果是True或False,例如以下簡單的範例:
PS > 1, "03", 5, 3 -contains "03"
True
PS > "a", "b", "c", "d" -ccontains "A"
False |
-like和-notlike:利用萬用字元進行相似比較
相似比較的-like和-notlike運算子可以利用萬用字元進行範圍更大的比對,比對的方式是左運算元裡是不是有右運算元?例如我們想要知道某個字串裡沒有good開頭的字,就可以將某個字串放在左運算元,而將「比對範式」當作右運算元。同樣的,若是要進行字母大小寫符合的比對,要改用c開頭的-clike或-cnotlike。
以下是四種萬用字元的相似比較說明。
|
|
|
可用來比對任何及任何數量的字元。例如xy*,只要是xy開頭皆能符合,包括xyz、xyw、xyx等,但如果是bao或cba就不符合。例如以下簡單的範例: |
PS > "Goodman" -like "good*"
True
# -clike,大小寫需符合
PS > "Goodman" -clike "good*"
False
PS > "Goodman" -like "god*"
False
PS > "192.168.1.1" -like "192.168.1.*"
True
# 相似比較亦可用在陣列或集合,結果會傳回相符的元素
# 你可試著將-like改成-notlike,並觀察運算結果
PS > "goodman", "guy", "goto", "good" -like "goo*"
goodman
good |
|
|
|
可用來比對任何的單一字元。例如x?z,只要是x開頭、z結尾的都符合,例如xyz、xaz、xgz,但如果是xz就不符合。例如以下簡單的範例: |
PS > "goodman" -like "goodm?n"
True
PS > "192.168.1.1" -like "192.16?.1.*"
Tru |
|
|
|
類似問號萬用字元,但可更精確的指定字元的範圍,例如x[i-k]z,是指x開頭、z結尾,且中間的字元是i到k的任一字元,因此只有xiz、xjz、xkz等三者符合。 |
PS > "xkz" -like "x[i-k]z"
True
PS > "goodman" -like "g[n-p]odm[a-c]n"
True" |
|
|
|
類似字元範圍,但更精確的指定可能的字元,例如x[iw]z,是指x開頭、z結尾,且中間的字元是i或w,因此只有xiz、xwz符合。 |
PS > "xiz" -like "x[iw]z"
True
# 第二個字元是[a-cpmo],
# 也就是第二個字元只要是a到c任一字元或p或m或o皆可。
PS > "goodman" -like "g[a-cpmo]odman"
True |
-match和-notmatch:比對部分內容
如果希望能更彈性的比對出部分內容,可以改用-match或-notmatch運算子,因為這些運算子支援規則運算式。例如想要找出某個字串變數裡有沒有man這個字,如果要找出的是man位於字尾的情況,可以利用前述的-like及星號萬用字元:
但如果要找出的是man可以位於字串裡的任何位置,則可以改用-match:
-match也可以搭配一些符號來達到更便利的部分比對,例如:
●^:表示開頭字元。
PS > "goodman" -match "^go"
True |
●$:表示結尾字元。
PS > "goodman" -match "man$"
True |
此外,前述-like用來表示字元範圍的方式,也能用在-match,例如以下簡單的範例:
PS > "hat" -match "h[ao]t"
True
PS > "hot" -match "h[ao]t"
True
PS > "h3t" -match "h[1-5]t"
True
PS > "h9t" -match "h[1-5]t"
False |
結語
本文介紹了Windows PowerShell的算術運算和比較運算。算術運算應該最為一般人熟悉,而比較運算的多樣,可能超過初次接觸者的想像。
不過Windows PowerShell的比較運算子雖然多樣,但依然很有條理:
|
|
|
-eq / -ne、-gt / -ge、-lt / -le。 |
|
|
|
-like / -notlike、-match / -notmatch、-contains / -notcantains。 |
而每種比較運算子又再根據字元的大小寫相同與否,延伸出c開頭和i開頭的運算子:
由於Windows PowerShell所提供的運算子相當豐富,為了不讓文章的篇幅太大而影響閱讀的學習效率,我們將於下一篇文章介紹其他的運算子。