這一部分著重于介紹Powershell的程序知識,讓我們能夠編寫功能強大的Powershell腳本,執行比較復雜的任務。
變量
變量使用$變量名
創建和引用。舉個例子,Get-Location
命令用于獲取當前工作目錄位置,它的別名是pwd
。那么我們可以使用下面的命令來創建一個變量,存儲當前目錄位置。
C:\Users\asddf> $current=pwd
然后我們訪問$current
,就可以獲取實際值了。
C:\Users\asddf> $current
Path
----
C:\Users\asddf
如果知道這個命令返回的實際是.NET對象的話,我們還可以更進一步,比方說直接訪問這個對象的Path
屬性,獲取值。
C:\Users\asddf> $current.Path
C:\Users\asddf
還有一個命令Get-Member
,別名是gm
,用于獲取對象的屬性。比方說,我們將Get-Location
命令的結果通過管道傳遞給Get-Member
命令,就會顯示下面的輸出。如果不了解.NET的話,可能感覺比較陌生。但是如果你懂得.NET和C#的話,就會像我一樣大喊一聲:“臥槽,還能這樣玩?!”
C:\Users\asddf> Get-Location|Get-Member
TypeName:System.Management.Automation.PathInfo
Name MemberType Definition
---- ---------- ----------
Equals Method bool Equals(System.Object obj)
GetHashCode Method int GetHashCode()
GetType Method type GetType()
ToString Method string ToString()
Drive Property System.Management.Automation.PSDriveInfo Drive {get;}
Path Property string Path {get;}
Provider Property System.Management.Automation.ProviderInfo Provider {get;}
ProviderPath Property string ProviderPath {get;}
如果我們要獲取對象的所有屬性,使用MemberType
參數。
C:\Users\asddf> pwd|gm -MemberType Property
我們還可以在變量上調用方法, 比如說將路徑轉換為全小寫。
C:\Users\asddf> $current.Path.ToLower()
c:\users\asddf
最后,如果不再需要一個變量,可以使用Remove-Variable
刪除變量,它的別名是rv
。
C:\Users\asddf> Remove-Variable current
操作符
來看看Powershell中支持的操作符。
數學運算符
首先,基本的數學運算符都是支持的。
PS D:\Desktop> $i=5
PS D:\Desktop> $sum=3+4*($i-3)/2
PS D:\Desktop> $sum
7
前置后置自增自減運算符也是支持的。
PS D:\Desktop> $i=0
PS D:\Desktop> $i--
PS D:\Desktop> $i++
PS D:\Desktop> ++$i
PS D:\Desktop> --$i
比較運算符
然后是比較運算符,這些和Linux Shell中很相似,有大于(-gt
),大于等于(-ge
),小于(-lt
),小于等于(-le
),等于(-eq
),不等于(-ne
)幾個。
字符串匹配運算符
-like
和-notlike
用于?*
這樣的通配符。
PS D:\Desktop> 'hello' -like '?ello'
True
PS D:\Desktop> 'hello' -notlike '?ello'
False
PS D:\Desktop> 'hello' -like '*o'
True
-match
和-notmatch
用于正則表達式。
PS D:\Desktop> 'aabcc' -match 'a*b?c+'
True
PS D:\Desktop> 'aab' -match 'a*b?c+'
False
包含和替換運算符
-contains
查找序列中是否包含某個元素。
PS D:\Desktop> 'hello','zhang3' -contains 'zhang3'
True
-replace
用于替換字符串中某個部分,當然正則表達式也是支持的。
PS D:\Desktop> 'hello zhang3' -replace 'zhang3','yitian'
hello yitian
分隔和連接運算符
-split
和-join
用于將一個字符串分為幾個子部分,或者將幾個子部分組合為一個字符串。
PS D:\Desktop> 'A B C DE' -split ' '
A
B
C
DE
PS D:\Desktop> 'A','B','C' -join ','
A,B,C
上面這些運算符都是大小寫不敏感的,如果需要大小寫敏感的功能,可以在運算符前面添加c
前綴。
PS D:\Desktop> 'yitian' -match 'Yitian'
True
PS D:\Desktop> 'yitian' -cmatch 'Yitian'
False
邏輯運算符
邏輯運算符有與(-and
)、或(-or
)、非(-not
或!
)以及異或(xor
)幾個,并且支持短路計算。
如果需要使用真值和假值字面量,可以使用$true
和$false
。
類型運算符
Powershell 和.NET平臺綁定,所以它是一門強類型的腳本。因此我們可以在腳本中判斷數據的類型,只要使用-is
或-isnot
運算符即可,類型需要寫到方括號中。這里的類型可以是所有合適的.NET類型。
PS D:\Desktop> 3.14 -is [Double]
True
PS D:\Desktop> 3.14 -isnot [Float]
True
重定向運算符
這個稍微比較麻煩一點。
首先是>
和>>
運算符,用于將標準輸出流重定向到文件,前者會覆蓋已有文件,后者則是追加到已有文件末尾。
然后我們來說說日志級別,如果有使用過某些語言的日志框架的話,就很好理解了。在這里,2代表錯誤、3代表警告、4代表信息、5代表調試信息。n>
和n>>
運算符就是用于將對應級別的輸出重定向到文件的,這兩者的區別和前面相同。n>&1
將對應級別的輸出和標準輸出一起重定向到文件。
最后就是*>
和*>>
了,這兩者將所有輸出信息重定向到文件。
需要注意,Powershell使用Unicode編碼來輸出信息。如果你需要使用其他類型的編碼,就不能使用重定向運算符了,而應該使用Out-File
命令。
特殊運算符
&
運算符將它后面的命令設置為后臺運行,當運行的命令需要阻塞當前終端的時候很有用。
.\\
運算符用于執行一個腳本或命令。如果執行的是Powershell腳本,那么腳本會在自己的作用域中執行,也就是說在當前環境下無法訪問被執行的腳本中的變量。
[]
運算符用于轉換變量的類型,比如說下面的代碼,就將pi
變量轉換為了Float
類型。
[Float]$pi = 3.14
$pi -is [Float]
.
運算符用于調用.NET對象的成員,它也可以用于執行腳本。當它用于執行腳本的時候,腳本會在當前作用域中執行。所以腳本結束之后,我們可以訪問腳本中的元素。
::
運算符用于調用類中的靜態成員,例如下面就會調用.NET平臺中DateTime
類的Now
屬性。
PS D:\Desktop> [DateTime]::Now
2017年5月18日 22:45:42
..
運算符用于創建一個范圍閉區間,例如下面這樣。
PS D:\Desktop> 1..3
1
2
3
PS D:\Desktop> 3..1
3
2
1
-f
運算符用于格式化數據,例如下面這樣。格式化方法和C#中的完全相同,所以如果不熟悉的話直接看在C#中如何格式化數據就行了。
PS D:\Desktop> 'My name is {0}, I am {1} years old' -f 'yitian',24
My name is yitian, I am 24 years old
$
運算符可以將字符串內部的變量轉換為實際的值,例如下面這樣。需要注意使用內插操作符的時候,外部字符串需要使用雙引號,否則Powershell會直接輸出字符串內容。
PS D:\Desktop> $name='yitian'
PS D:\Desktop> $age=24
PS D:\Desktop> "My name is $name, I am $age years old."
My name is yitian, I am 24 years old.
@()
運算符用于將一系列值轉換為一個數組。假如在腳本中有一個函數可能返回0、1或多個值,就可以使用這個操作符,將一系列值合并為一個數組,方便后續處理。
,
逗號運算符如果放置在單個值前面,就會創建一個包含這個值的單元素數組。
條件判斷
if判斷
Powershell中的條件判斷和一般的編程語言以及Shell編程都很類似,直接看代碼就能理解。
$condition = $true
if ($condition -eq $true) {
Write-Output "condition is $true"
}
elseif ($condition -ne $true ) {
Write-Output "condition is $false"
}
else {
Write-Output "other ocndition"
}
switch判斷
如果需要多重判斷,可以考慮使用switch語句。一個典型的switch如下所示。
$n = 4
switch ($n) {
1 {"n is 1"}
2 {"n is 2"}
3 {"n is 3"}
default {"n is others"}
}
其實細說起來,這個switch的坑還是不少的。例如,switch語句可以接受多個值來測試,在switch語句中還可以編寫多個case相同的語句。這里我就不細說了,想具體了解的話直接看官方文檔 about_Switch吧。
循環語句
提醒一下,不管是哪種循環語句,在循環體內都可以使用break
或continue
中斷/繼續循環。
do循環
首先來看看do-while循環,先執行循環體,然后判斷是否滿足條件,如果滿足條件則繼續執行。
$i = 0
do {
$i++
Write-Output $i
}while ($i -ne 3)
然后是do-until循環,和do-while類似,不過當條件不滿足的時候才會繼續循環,如果滿足條件則退出循環。
$i = 0
do {
$i++
Write-Output $i
}until ($i -eq 3)
while循環
while循環是先判斷循環條件,滿足條件時執行循環。
$i = 0
while ($i -lt 3) {
Write-Output $i
$i++
}
for循環
for循環可以看做是while循環的另一種形式,常用于固定次數的循環。
for ($i = 0; $i -ne 3; $i++) {
Write-Output $i
}
for-each循環
for-each循環用于遍歷一個集合中的所有元素。
$array = @(1, 2, 3, 4)
foreach ($i in $array) {
Write-Output $i
}
值得一提的是,for-each語句用在管道上時,還有以下一種用法。
<command> | foreach {<beginning command_block>}{<middle command_block>}{<ending command_block>}
使用這種方法時,for-each后面可以跟三個語句塊,第一個語句塊是開始語句塊,在循環前執行一次,常用來初始化一些數據;第三個是結束語句塊,在循環結束之后執行一次,常用于統計一些循環數據;第二個就是正常的循環語句塊,會循環多次。
函數
定義函數
定義函數使用function
關鍵字。
function hello {
Write-Output 'Hello Powershell'
}
定義好函數之后,就可以使用函數名來調用函數了。
hello
函數的參數
函數當然也可以帶參數了,參數列表有兩種寫法:第一種是C風格的,參數列表寫在函數名后面,使用小括號分隔開;第二種方式是在方法體中,使用param
關鍵字聲明參數。這兩種方法是完全等價的,當然我習慣上還是喜歡使用第一種方式。
Powershell是一種強類型的腳本語言,所以可以在參數列表上添加參數類型,參數類型是可選的,不過我還是推薦寫的時候帶上類型,方便閱讀和類型檢查。
function Say-Hello ([string] $name) {
Write-Output "Hello, $name"
}
function Say-Hello2 {
param([string] $name)
Write-Output "Hello, $name"
}
調用帶參數的函數時,需要向調用命令那樣,使用-參數名
來傳遞參數,例如下面這樣。
Say-Hello -name 'yitian'
默認參數
Powershell支持默認參數,直接用賦值號=
在參數列表上指定參數默認值即可。
function Say-Hello3 {
param([string] $name = 'zhang3')
Write-Output "Hello, $name"
}
位置參數
Powershell也支持位置參數,它會把所有參數包裝到$args
數組中,所以我們可以通過這個變量訪問所有位置的參數。例如下面,將所有參數合并一個字符串,然后打印出來。
function Say-Hellos {
$names = $args -join ','
Write-Output "Hello, $names"
}
這個函數調用時候需要指定多個參數,注意不要在多個參數之間添加括號,否則會變成一個數組參數,而不是多個參數。
Say-Hellos 'yitian' 'zhang3' 'li4'
開關參數
開關參數沒有類型,作用僅僅是標志是或者否。如果在使用函數的時候帶上開關參數,那么它就是開的狀態,否則就是關的狀態。開關參數需要指定參數類型為switch
。
function Answer-Hello ([switch] $yes) {
if ($yes) {
Write-Output "Hi"
}
}
然后在調用時就可以看出區別了。
Answer-Hello -yes
Answer-Hello
函數返回值
最后來說說函數返回值。這個其實也很簡單,只要使用return
語句就可以了。
function Add ([double]$a, [double]$b) {
$c = $a + $b
return $c
}
然后我們調用函數,就可以看到結果了。
Add -a 3 -b 5
關于Powershell編程的知識就介紹到這里,其實如果看看官方文檔的話,就知道這里介紹的也僅僅是一部分而已。不過這一部分對于我們日常使用和學習基本上也夠用了。
如果要查看詳細幫助的話,可以運行一下下面的命令,這樣會顯示所有和Powershell相關的幫助文檔。
Get-Help about*
然后,就可以閱讀自己感興趣的部分了。比方說,如果我們想了解用Powershell編寫類,就可以使用下面的命令。如果想在瀏覽器中瀏覽器在線版本,加上-online
參數即可。
Get-Help about_Classes
參考資料
http://windowsitpro.com/powershell/windows-powershell-operators