这一部分着重于介绍Powershell的程序知识,让我们能够编写功能强大的Powershell脚本,执行比较复杂的任务。
变量
变量使用$变量名
创建和引用。举个例子,Get-Location
命令用于获取当前工作目录位置,它的别名是pwd
。那么我们可以使用下面的命令来创建一个变量,存储当前目录位置。
C:Usersasddf> $current=pwd
然后我们访问$current
,就可以获取实际值了。
C:Usersasddf> $current
Path
----
C:Usersasddf
如果知道这个命令返回的实际是.NET对象的话,我们还可以更进一步,比方说直接访问这个对象的Path
属性,获取值。
C:Usersasddf> $current.Path
C:Usersasddf
还有一个命令Get-Member
,别名是gm
,用于获取对象的属性。比方说,我们将Get-Location
命令的结果通过管道传递给Get-Member
命令,就会显示下面的输出。如果不了解.NET的话,可能感觉比较陌生。但是如果你懂得.NET和C#的话,就会像我一样大喊一声:“卧槽,还能这样玩?!”
C:Usersasddf> 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:Usersasddf> pwd|gm -MemberType Property
我们还可以在变量上调用方法, 比如说将路径转换为全小写。
代码语言:javascript复制C:Usersasddf> $current.Path.ToLower()
c:usersasddf
最后,如果不再需要一个变量,可以使用Remove-Variable
删除变量,它的别名是rv
。
C:Usersasddf> Remove-Variable current
操作符
来看看Powershell中支持的操作符。
数学运算符
首先,基本的数学运算符都是支持的。
代码语言:javascript复制PS D:Desktop> $i=5
PS D:Desktop> $sum=3 4*($i-3)/2
PS D:Desktop> $sum
7
前置后置自增自减运算符也是支持的。
代码语言:javascript复制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编程都很类似,直接看代码就能理解。
代码语言:javascript复制$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如下所示。
代码语言:javascript复制$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循环,先执行循环体,然后判断是否满足条件,如果满足条件则继续执行。
代码语言:javascript复制$i = 0
do {
$i
Write-Output $i
}while ($i -ne 3)
然后是do-until循环,和do-while类似,不过当条件不满足的时候才会继续循环,如果满足条件则退出循环。
代码语言:javascript复制$i = 0
do {
$i
Write-Output $i
}until ($i -eq 3)
while循环
while循环是先判断循环条件,满足条件时执行循环。
代码语言:javascript复制$i = 0
while ($i -lt 3) {
Write-Output $i
$i
}
for循环
for循环可以看做是while循环的另一种形式,常用于固定次数的循环。
代码语言:javascript复制for ($i = 0; $i -ne 3; $i ) {
Write-Output $i
}
for-each循环
for-each循环用于遍历一个集合中的所有元素。
代码语言:javascript复制$array = @(1, 2, 3, 4)
foreach ($i in $array) {
Write-Output $i
}
值得一提的是,for-each语句用在管道上时,还有以下一种用法。
代码语言:javascript复制<command> | foreach {<beginning command_block>}{<middle command_block>}{<ending command_block>}
使用这种方法时,for-each后面可以跟三个语句块,第一个语句块是开始语句块,在循环前执行一次,常用来初始化一些数据;第三个是结束语句块,在循环结束之后执行一次,常用于统计一些循环数据;第二个就是正常的循环语句块,会循环多次。
函数
定义函数
定义函数使用function
关键字。
function hello {
Write-Output 'Hello Powershell'
}
定义好函数之后,就可以使用函数名来调用函数了。
代码语言:javascript复制hello
函数的参数
函数当然也可以带参数了,参数列表有两种写法:第一种是C风格的,参数列表写在函数名后面,使用小括号分隔开;第二种方式是在方法体中,使用param
关键字声明参数。这两种方法是完全等价的,当然我习惯上还是喜欢使用第一种方式。
Powershell是一种强类型的脚本语言,所以可以在参数列表上添加参数类型,参数类型是可选的,不过我还是推荐写的时候带上类型,方便阅读和类型检查。
代码语言:javascript复制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"
}
这个函数调用时候需要指定多个参数,注意不要在多个参数之间添加括号,否则会变成一个数组参数,而不是多个参数。
代码语言:javascript复制Say-Hellos 'yitian' 'zhang3' 'li4'
开关参数
开关参数没有类型,作用仅仅是标志是或者否。如果在使用函数的时候带上开关参数,那么它就是开的状态,否则就是关的状态。开关参数需要指定参数类型为switch
。
function Answer-Hello ([switch] $yes) {
if ($yes) {
Write-Output "Hi"
}
}
然后在调用时就可以看出区别了。
代码语言:javascript复制Answer-Hello -yes
Answer-Hello
函数返回值
最后来说说函数返回值。这个其实也很简单,只要使用return
语句就可以了。
function Add ([double]$a, [double]$b) {
$c = $a $b
return $c
}
然后我们调用函数,就可以看到结果了。
代码语言:javascript复制Add -a 3 -b 5
关于Powershell编程的知识就介绍到这里,其实如果看看官方文档的话,就知道这里介绍的也仅仅是一部分而已。不过这一部分对于我们日常使用和学习基本上也够用了。
如果要查看详细帮助的话,可以运行一下下面的命令,这样会显示所有和Powershell相关的帮助文档。
代码语言:javascript复制Get-Help about*
然后,就可以阅读自己感兴趣的部分了。比方说,如果我们想了解用Powershell编写类,就可以使用下面的命令。如果想在浏览器中浏览器在线版本,加上-online
参数即可。
Get-Help about_Classes
参考资料
https://msdn.microsoft.com/en-us/powershell/reference/5.1/microsoft.powershell.core/about/about_operators?f=255&MSPPError=-2147217396
http://windowsitpro.com/powershell/windows-powershell-operators