Windows PowerShell講座(6)—運算子(上)
發佈日期: 2008 年 4 月 21 日
**作者:**賴榮樞
www.goodman-lai.idv.tw
Windows PowerShell 提供了豐富的運算子讓我們處理程式裡的各種運算,我們將分兩篇文章來說明,本文將先說明其中的算術運算、指定運算、比較運算。
本頁內容
運算式、運算子、運算元
算術運算
指定運算
比較運算
結語
程式的執行過程充滿了許許多多的運算,在程式裡,我們會將運算的過程寫成運算式,而程式執行運算式便能完成運算。
運算式、運算子、運算元
運算式是由運算元和運算子所構成,運算子是運算式裡參與運算的符號(例如算術運算的 +、-、*、/ ),而運算元則是參與運算的資料,這些資料可以直接以數值表示,也可以是變數、常數、或另一個運算式,有些程式語言甚至允許物件或函式作為運算元。
此外,根據運算子所作用的運算元數量,運算子又可分成一元運算子、二元運算子、三元運算子;例如加法運算需要兩個運算元,因此加法運算子即為二元運算子。
算術運算
Windows PowerShell 提供的算術運算子包括了加減乘除四則運算、餘數運算、負號,以及遞增和遞減運算。這些運算子列表如下。
運算子 |
說明 |
簡例 |
---|---|---|
+ |
加 |
123 + 456 |
- |
減 |
456 - 123 |
* |
乘 |
123 * 456 |
/ |
除 |
456 / 123 |
% |
取餘數 |
456 % 123 |
- |
負號(一元運算子) |
-456 |
++ |
遞增(一元運算子) |
$var = 10 |
-- |
遞減(一元運算子) |
$var = 10 |
加、減、乘、除、餘數運算、負號應該已為一般人熟悉,於此不再贅述,但要提醒您的是,加法運算子亦可作為字串連接之用(例如 "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 )。
指定運算
指定運算子都是二元運算,可以將運算子右側的值、物件、或另一個運算式的結果,指定給運算子左側的變數、屬性、或物件。我們之前就已經使用過的等號 (=),是最常見的指定運算子。但是除了等號之外,Windows PowerShell 還提供了另外五種具有算術運算能力的指定運算子。這些運算子列表如下。
運算子 |
說明 |
簡例 |
---|---|---|
= |
將運算子右側的值,指定給運算子左側的變數。 |
$var = 3 |
+= |
將運算子左側的變數值,加上運算子右側的值,再指定給運算子左側的變數。 |
$var += 5(寫法等同於 $var = $var + 5) |
-= |
將運算子左側的變數值,減去運算子右側的值,再指定給運算子左側的變數。 |
$var -= 5(寫法等同於 $var = $var - 5) |
*= |
將運算子左側的變數值,乘以運算子右側的值,再指定給運算子左側的變數。 |
$var *= 5(寫法等同於 $var = $var * 5) |
/= |
將運算子左側的變數值,除以運算子右側的值,再指定給運算子左側的變數。 |
$var /= 5(寫法等同於 $var = $var / 5) |
%= |
將運算子左側的變數值,除以運算子右側的值,並取餘數,再指定給運算子左側的變數。 |
$var %= 5(寫法等同於 $var = $var % 5) |
指定運算最需要注意的,是指定運算子左右兩側的資料型別是否對等,以及左側的變數能不能容納右側的值,例如應該要避免將字串資料指定到整數型別的變數,或者要避免將小數值放進整數型別變數;前者可能會造成錯誤,也可能會因型別自動轉換而導致意料外的結果,而後者會導致部分的資料損毀(例如將 3.14 指定到整數型別變數,變數裡的值會只剩下整數 3)
Windows PowerShell 的指定運算還有一些有趣且需要留意的地方。
16 進位值。我們可以將 16 進位值指定給變數,但是 Windows PowerShell 會先將值轉換成十進位,再將值以整數型別指定給變數:
# 16 進位的表示是以 0x(前者為數字零)作為前置 PS > $var = 0x10 PS > $var 16
科學記號。我們能以科學記號的表示法將數值指定給變數,但是 Windows PowerShell 換先還原,再將數值指定給變數:
PS > $var = 4.3456e3 PS > $var 4345.6
KB、MB、GB。慣用的 KB、MB、GB 等位元組計量方式,也可以用在指定運算,但是 Windows PowerShell 在將數值指定到變數之前,會先將值轉換成以位元組為計量的方式(K = 1024、M = 1024 * 1024、G = 1024 ^ 3):
PS > $var = 10mb # 小寫的 mb 亦可 PS > $var 10485760 # 10 * 1024 * 1024 PS > $var = 0.3kb PS > $var 307.2 # 0.3 * 1024
一行多個指定運算。只要以逗號隔開,Windows PowerShell 允許在一行程式碼執行多個指定運算,例如以下簡單的範例:
# 變數和數值的數量一樣多,相當於: # $i = 1; $j = 2; $k = 3 PS > $a, $b, $c = 1, 2, 3 # 變數的數量多過數值,相當於: # $a = 1; $b = 2; $c = 3, 4, 5 PS > $a, $b, $c = 1, 2, 3, 4, 5 # 承上例 $c = 3, 4, 5 # 故而 $x =3、$y = 4、$z = 5 PS > $x, $y, $z = $c # 數值的數量多過變數,相當於: # $n = 1; $o = 2; $p # $p 沒有指定值,因此為 Null PS > $n, $o, $p = 1, 2 # 一次將同一值指定給數個變數 PS > $d = $e = $f = 3
關於變數的指定運算,可以參考這個系列文章的《 Windows PowerShell 講座 (4)— 變數(https://www.microsoft.com/taiwan/technet/columns/profwin/66-Winpowerwshell4.mspx)》,這篇文章討論了許多指定運算之後的資料型別轉換例子,以及指定變數值的 Set-Variable。
比較運算
比較運算的結果會得到真(True)或偽(False),因此經常用在需要決策的陳述式,例如 if 或 while。但是與一般程式語言不同的是,Windows PowerShell 的比較運算子並非常見的代數比較符號,而是英文字的縮寫,因為 > 或 < 之類的符號已經用在輸出重導。這些運算子列表如下。
運算子 |
說明 |
簡例 |
結果 |
---|---|---|---|
-le |
小於或等於 |
10 -le 10 |
True |
-like |
相似(以萬用字元比較) |
"One" -like "o*" |
True |
-notlike |
不相似(以萬用字元比較) |
"One" -notlike "o*" |
False |
-match |
符合(以規則運算式比較) |
"book" -match "[iou]" |
True |
-notmatch |
不相符(以規則運算式比較) |
"book" -notmatch "[iou]" |
False |
-contains |
包含(運算子左邊含有右邊的值) |
"n", "o", "e" -contains "O" |
True |
-notcontains |
不包含(運算子左邊沒有右邊的值) |
"n", "o", "e" -notcontains "O" |
False |
乍看以上表格,您可能會覺得 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.*" True
字元範圍([字元-字元]):類似問號萬用字元,但可更精確的指定字元的範圍,例如 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 及星號萬用字元:
PS > $var -like "*man"
但如果要找出的是 man 可以位於字串裡的任何位置,則可以改用 -match:
PS > $var -match "man"
-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 開頭的運算子:
原型(例如 -eq):大小寫視為相同。
c開頭(例如 -ceq):大小寫視為不同。
i開頭(例如 -ieq):大小寫視為相同。
由於Windows PowerShell 所提供的運算子相當豐富,為了不讓文章的篇幅太大而影響閱讀的學習效率,我們將於下一篇文章介紹其他的運算子。