PowerShell入门指南(三)·一门新的编程语言
作为独立的编程语言
作为一门独立的语言来说,PowerShell
是非常地Powerful,我们先来了解一下它的特点:
特点
破天荒的方便
诸如存储计算中
GB
,MB
,KB
单位等;数组声明中的1..n
和下标为-1
的处理;还有所见即所得,通俗易懂的动词+名词结构的Cmdlet(PowerShell命令的称呼)。
还有自带的文档支持也很是丰富,只要熟练掌握Get-Help
命令,其他命令的用法均可通过Get-Help
查到面向对象
良心啊,这个语言竟然是面向对象的
与面向过程相比,面向对象更方便更容易描述现实世界,也算赶上了时髦。依托 .NET
正所谓大树下面好乘凉,
PowerShell
绑上.NET
这个大款了,借助.NET
平台强大的类库,几乎让一切都成为可能。强大的兼容性
完全兼容
Windows
平台上其它调用,如可执行文件(exe),批处理bat/cmd和VBscript等, 在Linux
和macOS
上也能很好地工作。基于平台的可扩展性
微软有个优点,与应用相比,它更喜欢做平台。
PowerShell
早已变成一个平台,在PowerShell
刚发布的第二年,微软的 System Center Operations Manager 和 SharePoint 就提供了针对该平台的组件,后来的活动目录,Hyper-V,Windows Azure,Office 365就更不用说了。除了微软,亚马逊的云平台管理,Dell的out-of-hand 管理,也都提供了基于PowerShell
的管理组件。PowerShell
俨然变成了一个标准,变成了一个规范。
使用Get-Help
快速入门
下面用一个简单例子说明如何Get-Help
,设想这样一个场景:
你想通过命令行查看所有进程,你第一个反应应该是用一个跟Process相关的命令来达到此目的,所以你可以会尝试执行:
1 | Get-Command *Process |
得知处理进程的命令有这些
然后再用 Get-Help Get-Process -full
就能得到 Get-Process
的详细用法以及使用范例
基本语法
背景
PowerShell
是一个强类型(变量一旦定义,其本身类型不可改变就是强类型,反之就是弱类型)的动态脚本语言,支持面向对象,支持调用系统API和 .NET
库。
受到了 Python
, Ksh
, Perl
, C#
, CL
, DCL
, SQL
, Tcl
, Tk
, Chef
, Puppet
等语言的影响,结合了以上语言的部分特性。
PowerShell
代码的外观和操作方式与C#的相似程度最高,不过也有它自己的特色。
关于空白字符
与 Python
等语言不同,**PowerShell
的解释器不会考虑代码中的空格或制表符**(这些字符统称空白字符)。这样一来,格式化代码就有很大的自由度,但是遵循某些规则将有助于提高代码的可读性。
代码块和代码基本结构
PowerShell
代码由一系列语句构成,每条语句可以使用一个分号结束,当然也可以不写。按照习惯是不写分号的,因此要用换行来区分不同的语句,如果必须写到一行中,那就在每一句后加个分号。
和C语系的大多数语言类似,PowerShell
是一种块结构的语言,这些块用 {
和 }
来界定,代码块可以包含任意多条语句,或者不包含任何语句,下面的示例还使用了缩进格式,这样能大大提高可读性,实际上编译器会自带缩进代码。一般情况下,每个代码块都有自己的缩进级别,代码块之间还能嵌套。
1 | { |
当然 PowerShell
的缩进不是强制的。
在 PowerShell
代码中,另一种常见的语句是注释,注释并不是能执行的语句,而是对代码的描述说明性文本。当代码运行时,解释器会忽略这些内容。
代码最好有注释,特别是处理较复杂的工作时,注释可以为正在进行的操作添加提示,例如“这行代码要求用户输入一个字符”、“此段代码是 LNP 编写的”。PowerShell
有两种添加注释方法
- 行注释:
#
- 块注释:
<#
和#>
1 | #这是一行注释 |
第一个 #>
后面的部分会被认为是 PowerShell
代码,因此出现错误。
还有特别的注意一点,**PowerShell
代码是不区分大小写的**,因此只要拼写正确的命令(或变量),而无需关心大小写即可执行,不过最好还是有一定规范。
PowerShell
脚本的基本结构
PowerShell
像 Python
一样,允许使用控制台直接输入命令进行交互,也可以事先把代码写入一个文件再作为脚本运行。
一个 PowerShell
脚本仅仅是一个包含 PowerShell
代码的文本文件。如果这个文本文件执行, PowerShell
解释器会逐行解释并执行它的的语句。PowerShell
脚本有点像以前 CMD
控制台上的批处理文件。可以通过非常简单的文本编辑工具创建 PowerShell
脚本。
PowerShell脚本文件的扩展名是 .ps1
执行策略限制
PowerShell
一般初始化情况下都会禁止脚本执行。脚本能否执行取决于PowerShell的执行策略。
1 | PS E:> ./MyScript.ps1 |
只有管理员才有权限更改这个策略。非管理员会报错。
查看脚本执行策略,可以通过在 PowerShell
控制台直接输入:Get-ExecutionPolicy
更改脚本执行策略,可以管理员启动PowerShell,在控制台输入:Set-ExecutionPolicy <策略>
策略|解释
-|-
Unrestricted|权限最高,可以不受限制执行任何脚本。
Default|为Powershell默认的策略,即Restricted
Restricted|不允许任何脚本执行
AllSigned|所有脚本都必须经过签名才能在运行
RemoteSigned|本地脚本无限制,但是对来自网络的脚本必须经过签名
如果要使用脚本功能又要兼顾安全性,我们就选择RemoteSigned
即在以管理员身份允许的 PowerShell
输入Set-ExecutionPolicy RemoteSigned
1 |
|
运行 PowerShell
脚本
当您的脚本编写成功后您可能第一次会像下面的方式运行它,也就是只输入脚本的文件名,会报错。
1 | PS E:> MyScript.ps1 |
解决办法很简单,如果脚本在当前工作目录,请在脚本文件明前添加./
,或者使用绝对路径。
1 | PS E:> .\MyScript.ps1 |
通过重定向创建脚本
如果想要执行的脚本不是很长,我们甚至可以直接在控制台中要执行的语句重定向给一个脚本文件。
1 | PS E:> '"Hello,World!"' > MyScript.ps1 |
这样有个缺点,就是您的代码必须放在闭合的引号中。这样的书写方式一旦在脚本内部也有引号时,是一件很痛苦的事。甚至您还可能希望在脚本中换行。下面的Here-strings例子不错,也就是将脚本文件通过@' '@
闭合起来。
1 | PS E:> @' |
Here-String以 @'
开头,以'@
结束.任何文本都可以存放在里面,哪怕是一些特殊字符,空号,白空格。但是如果您不小心将单引号写成了双引号,PowerShell
将会把里面的变量进行解析。
通过编辑器创建脚本
其实最方便的还是使用文本编辑器直接编写代码,保存成PS1文件,右键即可执行。
这里推荐使用Visual Studio Code(以下简称VSC),VSC提供了PS1的自动补全(安装插件)、语法高亮、自动缩进、格式化代码、断点调试等功能。
变量
变量可以临时保存数据,因此可以把数据保存在变量中,以便进一步操作。PowerShell
的变量定义非常方便。
我们可以用 $变量名=初值
的方法定义变量,解释器会根据所赋的初值判断变量类型,类似于C#的 var
关键字或C++11中的 auto
关键字PowerShell
不需要显示地去声明,可以自动创建变量,只须记住变量的前缀为$.
创建好了变量后,可以通过变量名输出变量,也可以把变量名存在字符串中。但是有个例外:单引号中的字符串不会识别和处理变量名。
选择变量名
在 PowerShell
中变量名均是以美元符 $
开始,剩余字符可以是数字、字母、下划线的任意字符,并且PowerShell变量名也对大小写不敏感($a
和 $A
是同一个变量)。
某些特殊的字符(比如$
等)在 PowerShell
中有特殊的用途,一般不推荐使用这些字符作为变量名。当然你硬要使用,请把整个变量名后缀用花括号括起来。
1 | PS C:/> ${"I"like $}=5.1 |
不能定义和保留变量名称相同的变量
使用ls variable:
列出当前使用的所有变量,刚启动的 PowerShell
执行此命令能看到 PowerShell
的所有自动化变量(一旦打开 Powershell
就会自动加载的变量,后面将会详细解释这些变量的作用)
1 | Name Value |
查看变量类型
变量可以自动存储任何PowerShell
能够识别的类型信息,可以通过 $变量名.GetType()
查看和验证 PowerShell
分配给变量的数据类型
1 | PS C:/> $num=10 |
删除变量
如果不想继续使用自定义的变量,可以使用del variable:变量名
的方法删除变量,注意此处无$
符号
1 | $a=0 |
PowerShell支持的变量类型和C#大体相同(没有了short、uint、ulong等),大多都继承自System.ValueType
类( .NET类),其基本数据类型包括
整型
类型 | 名称 | 允许的值 | 所属类 |
---|---|---|---|
byte | 无符号整数(1字节) | 0~255之间的整数 | System.Byte |
sbyte | 有符号整数(1字节) | -128~127之间的整数 | System.SByte |
int16 | 有符号短整型(2字节) | -32768~32767之间的整数 | System.Int16 |
uint16 | 无符号短整型(2字节) | 0~65535之间的整数 | System.UInt16 |
int | 有符号整型 | -2147483648~2147483647之间的整数 | System.Int32 |
uint32 | 无符号整型 | 0~4294967295之间的整数 | System.UInt32 |
long | 有符号长整数(8字节) | -9223372036854775808~9223372036854775807之间的整数 | System.Int64 |
ulong | 无符号长整数(8字节) | 0~18446744073709551615之间的整数 | System.UInt64 |
其实 int
、long
、以及下面的 float
都是 .NET的语法糖,真正的原生类型名是int32
、int64
、single
之类的类名
浮点型
浮点数标准形式(float
和double
)
$+/-m×2^e$
其中m为尾数,e为阶码,尾数是一个非负数,阶码是一个整数
PowerShell还支持一个特别的浮点数类型 decimal
,其形式为
$+/-m×10^e$
类型 | 名称 | 指数 | m范围 | e范围 | 近似最小值 | 近似最大值 | 所属类 |
---|---|---|---|---|---|---|---|
float | 单精度浮点数 | 2 | 0~$2^{24}$ | -149~104 | $1.5×10^{-45}$ | $3.4×10^{38}$ | System.Single |
double | 双精度浮点数 | 2 | 0~$2^{53}$ | -1075~970 | $5.0×10^{-324}$ | $1.7×10^{308}$ | System.Double |
decimal | 16字节浮点数 | 10 | 0~$2^{96}$ | -28~0 | $1.0×10^{-28}$ | $7.9×10^{28}$ | System.Decimal |
其他简单类型
除了数值类型以外,还有3种基本类型
类型 | 名称 | 允许的值 | 所属类 |
---|---|---|---|
char | 字符型 | 一个Unicode字符,存储0~65535之间的整数 | System.Char |
bool | 布尔型 | 布尔值: $true 或 $false (必须加$ 符号) |
System.Boolean |
enum | 枚举 | 限定取值一组命名常量的独特的值类型 | System.Enum |
datetime | 时间型 | 包含日期、时间的类型 | System.DateTime |
string | 字符串 | 一组字符 | System.String |
注意 C/C++的 char
仅支持ASCII里面的256个字符, PowerShell
和 C#
的 char
是支持Unicode的,
PowerShell和C#的string
类型并不是继承自 System.ValuType
类,而是继承自 System.Object
类,因此严格来说 string
类型并非是简单类型。
**PowerShell的转义字符是 ` 而不是 \**,这也是和C#的一个区别
1 | #使用char |
赋值和返回值
赋值操作符为 =
,几乎可以把任何数据赋值给一个变量,甚至一条cmdlet命令
,因为 PowerShell
支持面向对象,对象可以包罗万象。
1 | PS D:\powershell\test> $item=ls |
弱类型与强类型
一般对 PowerShell
变量重新赋值时,变量类型会自动改变,这是弱类型语言的特点;
而 PowerShell
依托的 .NET是强类型的,所以 PowerShell
可以使用强类型。
强类型语言在速度上略逊于弱类型语言,但是强类型定义语言带来的严谨性又能避免不必要的错误。
可以在变量前添加类型限定符使该变量变为强类型,可以确保变量的类型不会随着赋值而改变
1 | [int]$num=123 #正确 |
类型转换
PowerShell
能够非常方便地将字符串等基本类型转换成期望的类型。之所以神奇,是因为 PowerShell
本身做了很多辛苦的工作,按照优先级:
- 直接赋值:输入类型和期望类型一致,可以直接交付。
- 基于语言的类型转换:当目标类型为
void
,Boolean
,String
,Array
,Hashtable
,PSReference
(i.e.: [ref]),XmlDocument
,Delegate
和Enum
时,基于语言的类型转换开始工作。 - Parse 转换:如果目标类型包含了
Parse()
方法,则采用它。 - Static Create 转换:如果目标类型包含静态的Create,则采用它。
- 构造函数转换:如果目标类型定义了构造函数,采用它。
- Cast 转换:如果目标类型定义了从源类型的显式或者隐式的操作符,则采用它。
- IConvertible 接口转换:如果目标类型实现了支持源类型
IConvertible
接口,则采用它。 - IDictionary 转换:如果源类型是词典或者哈希表,会尝试创建一个实例,然后来填充name和value属性。
- PSObject 属性转换:如果源类型是
PSObject
,通过目标类型的默认的构造函数创建一个实例,然后使用PSObject
中的属性名称和值来填充实例的属性。 - TypeConverter 转换:如果存在注册的
TypeConverter
或PSTypeConverter
来处理转换,则使用它。
注意对浮点数向整数进行类型转换时,会自动四舍五入!!
如果要C++/C#那种向下取整的方法请使用 [math]::Floor()
函数
看几个转换的例子
1 | PS D:/test> $s=12.56 |
[convert]::ToInt32()
是 .NET System.Convert
类提供的转换函数convert
类中的转换函数格式为:TO
+原生类型名()
,这里的原生类型名指的是各个类型实际类名
常用:
[convert]::ToInt32()
[convert]::ToSingle()
[convert]::ToDouble()
[convert]::ToBoolean()
[convert]::ToString()
convert
类提供了一系列方法来完成不同变量之间的转换,获得函数列表及使用方法请参考微软的 .NET文档Convert类 方法列表
运算符
注意逻辑运算符和比较运算符的写法,不支持 C#
的&&
||
!
==
!=
<
>
>=
<=
这些运算符
1 | #加 减 乘 除 取余 |
条件分支
if else
if
和 else
用法和C#完全一样,除了大括号不允许省略,多分支时还多了个elseif
可用,和Python
的 elif
作用相同
1 | if($true -and $true) { |
switch
PowerShell的switch
非常灵活,使用起来较为方便
相对C#或C++,PowerShell的switch不需要写`case:``,但是必须写大括号
1 | $a="Beijing" |
默认比较运算符为-eq
,你也可以使用下面的例子自定义比较条件,必须保证表达式返回boolen类型($true和$false)
1 | $v=18 |
循环
接下来介绍循环
for循环
PowerShell
的 for
循环类似于C#
,看一个样例:
1 | for($i=0;$i -lt 10;$i++) |
do-while循环
Do
和 While
可能产生死循环,为了防止死循环的发生,因此我们必须确切的指定循环终止的条件。指定了循环终止的条件后,一旦条件不满足就会退出循环。do-while()
会先执行再去判断,能保证循环至少执行一次。
1 | do |
只使用while
1 | $n=5 |
跳出循环
使用 continue
关键字,可以终止当前循环,跳过 continue
后其它语句,重新下一次循环。
跳出循环语句使用 break
关键字
1 | $n=1 |
还有一种循环 foreach
,等到我们讲到数组再说
数组
定义数组
在 PowerShell
中创建数组可以使用逗号
1 | PS C:/Powershell> $nums=2,0,1,2 |
对于连续的数字数组可以使用一个更快捷的方法:
1 | PS C:/Powershell> $nums=1..5 |
对象数组的多态
像变量一样,如果数组中元素的类型为弱类型,默认可以存储不同类型的值。
1 | PS C:/Powershell> $array=1,"2019",([Guid]::NewGuid()),(get-date) |
空数组和单元素数组
对数组元素可以查看它的公有属性,比如长度
只需要输入$数组名.Count
即可显示数组长度
空数组
1 | PS C:/Powershell> $a=@() |
单元素数组
1 | PS C:Powershell> $a=,"moss" |
使用数组
遍历
直接法
将数组作为单独一行将会自动遍历这个数组的所有元素
1 | PS C:/> $a=1..10 |
for
循环遍历
1 | PS C:/> $a=1..5 |
foreach
遍历法
还有一种遍历的方法,用到了之前提到的 foreach
语句
意思是使用变量 $n
对 $a
元素进行迭代,这实际上是一种对可迭代对象的访问算法
在 C#
也有这种语法
1 | $a="A","B","C","D","E" |
foreach
还有一种遍历的写法
这里我们需要先了解一下管道
管道的符号 |
管道允许将它左侧命令的输出结果发送到右侧做命令的参数
管道并不是什么新事物,以前的Cmd控制台也有重定向的命令,例如Dir | More可以将结果分屏显示。
传统的Cmd管道是基于文本的,但是 PowerShell
是基于对象的
列出当前目录下的目录和文件,然后根据文件名降序排列,再投影(数据库术语)文件名,文件大小,文件的修改时间:
1 | PS D:/test> ls | Sort-Object -Descending Name | Select-Object Name,Length,LastWriteTime |
可迭代对象(比如数组)可以由管道送到一些命令上进一步处理foreach
就可以接受管道送来的可迭代对象,并进行遍历
1 | $array="A","B","C","D","E" |
将数组逆序输出
1 | PS C:/Powershell> $books="A1","B2","C3" |
访问某些元素
与C#相同,数组的元素可以使用索引寻址,第一个元素的索引为0,第i个元素的索引为i-1,最后一个元素的索引为Count-1,但是 PowerShell
为了使用方便,直接可以将 -1 作为最后的一个元素的索引(参考了 Python
的语法)
1 | PS C:/Powershell> $books="1A","2B","3C" |
从数组中选择多个元素
1 | PS C:/Powershell> $result=ls |
给数组添加元素
因为PowerShell数组在内存中是顺序存储的,所以数组的大小必须是确定的,这样才方便分配存储空间,所以给数组增加元素其实相当于创建一个新的数组,只不过之后会把原来的副本删除。在当前数组追加元素可以使用 +=
操作符。
1 | PS C:/Powershell> $books="A1","B2","C3" |
删除指定位置元素
采用截断重连法删除指定元素
1 | PS C:/Powershell> $num=1..4 |
复制数组
数组属于引用类型,使用默认的的赋值运算符在两个变量之间赋值只是复制了一个引用,两个变量共享同一份数据。这样的模式有一个弊病如果其中一个改变也会株连到另外一个。所以复制数组最好使用 Clone()
方法( System.Array
类的成员函数),除非有特殊需求。
1 | PS C:/Powershell> $chs=@("A","B","C") |
强类型数组
PowerShell
数组一般具有多态性,如果你不指定元素的具体类型,解释器会自动选择合适的类型存储每个元素。如果要统一限制所有元素的类型,可是使用类型名和一对方括号作为数组变量的类型。这样每当赋值时,会自动类型检查。如果目标数据类型不能转换成功,就会抛出一个异常,这样的数组被称为强类型数组
定义方法[类型[]]$数组名=初值
1 | PS C:/Powershell> [int[]] $nums=@() |
命令返回数组
当我们把一个命令的执行结果保存到一个变量中,可能会认为变量存放的是纯文本。
但是,事实上 PowerShell
会把文本按每一行作为元素存为数组。如果一个命令的返回值不止一个结果时, PowerShell
也会自动把结果存储为数组
1 | PS C:/Powershell> $IPcfg=ipconfig |
使用数组存储结果
判断一个变量是否为数组
1 | PS C:/Powershell> $ip=ipconfig |
使用真实的对象操作
为什么不愿把IPconfig返回的结果称为对象,因为它不是真正Cmdlet命令(事实上ipconfig是一个单独的程序),真正的 PowerShell
命令返回的数组元素可不止一个字符串,它是一个内容丰富的对象。
1 | PS D:/test> $list=ls |
上面的例子中数组的每一个元素存放的是一个 System.IO.DirectoryInfo
对象。
当我们输出这些对象时,PowerShell
会自动帮我们把它转换成友好的文本格式。
对于任何一个对象都可以使用 Format-List *
来查看它所有的属性和方法。
1 | PS D:/test> $list[0]|fl * |
函数
函数是自定义的 Powershell
代码,有三个原则:
- 简短:函数名简短,并且显而易见。
- 聚合:函数可以完成多个操作。
- 封装和扩展:将一批
Powershell
语句进行封装,实现全新的功能需求。
函数的结构由三部分组成:函数名,参数,函数体
定义函数
脚本中函数的定义方法
函数可以在文本编辑器上编写,写完以后复制进 PowerShell
控制台即可。如果控制台设置为快速编辑模式,从记事本复制后,直接在控制台鼠标右键即可完成粘贴(Windows 10默认开启了快速编辑模式)
1 | function FuncName(args[]) #括号可省略 |
控制台上多行输入定义函数
1 | PS C:/PowerShell> function MyPing |
把函数精简成一行
我们可以将一个函数定义在一行上,但是这样阅读和理解起来就不方便,所以要在每条命令后加分号进行分割(最后一句可以不写;
)
1 | PS C:/PowerShell> function cd...{ cd.. ; cd.. } |
使用函数作为别名
假如 PowerShell
不支持 Get-SystemVersion
命令,你可以通过定义函数实现这个功能:
1 | function get-systemversion |
更新函数
如果要更新已经定义好的函数,简单的方法是重新定义,这样新的定义会覆盖旧的定义。但是如果函数代码没有保存副本,可以先将函数定义导出到ps文件,然后就可以编辑了。
1 | PS C:/PowerShell> function MyPing |
删除函数
控制台定义的函数只会在当前会话生效,一旦控制台退出,会自动消失。在不关闭控制台的条件下删除一个已经定义好的函数,可是使用虚拟驱动器的方法:
1 | function cc{"hello"} |
输入输出函数
用于脚本文件的编写
输入
PowerShell提供了 Read-Host
命令,可以接收返回用户在控制台输入的字符
1 | $name=read-host "请输入你的名字" |
注意到
- 提示信息(如果有)后面自动加了个冒号;
- 用户键入任何信息都被作为该命令的返回结果;
- 可以把键入的信息传递给一个变量;
输出
有两种输出命令Write-Host
和Write-Output
若输出字符串不包含空白字符可以不加引号
Write-Host
当需要展示一个特定信息,比如使用其他颜色来吸引人们的注意力的时候,可使用 Write-Host
命令
Write-Host
和其他Cmdlets一样使用管道,但是它不放置任何数据道管道中。反而会直接写到宿主应用程序的界面。正如此,可以使用-ForegroundColor
和 -BackgroundColor
参数将前景和背景设置为其他颜色:
1 | write-host "啊哈" -ForegroundColor White -BackgroundColor Red |
注:不是每个使用PowerShell的应用程序都支持其他颜色,也并不是每个应用程序都支持所有颜色。
该输出方法不适用于常规的输出结果,因为 Write-Host
命令输出到屏幕的任何东西都无法被捕捉。若执行远程命令或无人值守命令(纯自动化), Write-Host
可能不会按照你的预期工作。因此,此命令仅仅用于与人进行直接交互。
Write-Output
Write-Output
命令会将对象发送给管道。由于它不会直接发送到显示界面,所以不允许你指定其他任何的颜色。
它是PowerShell
默认使用的一个Cmdlets,默认输出方式即使用该命令,即使你没有指定,PowerShell
会在底层将信息传递给Write-Output
命令(就是一行直接写一个变量就能直接输出的情况),另外这个命令还有两个别名 write
和 echo
1 | write-host ACB #无空白字符可以不写引号 |
Write-Output
输出基本过程为:
Write-Output
命令将string
类型的对象Hello World!
放入管道中;- 管道中只有这个
string
对象,其会直接到达管道的末端,也就是Out-Default
命令;Out-Default
命令将对象传递给Out-Host
命令;Out-Host
命令要求PowerShell
的格式化系统格式化该对象。Out-Host
将格式化的结果集放在显示界面上
还有一点,在输出多个对象时,Write-Host
会以空格隔开各对象Write-Output
会以换行隔开各对象
1 | write-host "ABC" "23232" |
其他的输出方式
Write-Warning/Verbose/Debug/Error
具体参考:微软官方文档
处理函数参数
PowerShell
函数可以接受参数,并对参数进行处理。函数的参数有3个特性:
- 任意参数:内部变量
$args
接受函数调用时接受的参数,$args
是一个数组类型; - 命名参数:函数的每一个参数可以分配一个名称,在调用时通过名称指定对应的参数;
- 预定义参数:函数在定义参数时可以指定默认值,如果调用时没有专门指定参数的值,就会保持默认值;
$args 万能参数
给一个函数定义参数最简单的是使用$args
这个内置的参数。它可以识别任意个参数。尤其适用那些参数可有可无的函数。
1 | function sayHello |
因为 $arg
是一个数组,可以用它很方便的写出求和函数
1 | function Add |
使用固定参数
1 | function StringContact($str1,$str2) |
给参数定义默认值
1 | function stringContact($str1="LN",$str2="P") |
使用强类型参数
通过之前的例子发现将用户的参数传递给函数显得比较混乱。罪魁祸首就是PowerShell
的参数解释器,它可以自动处理和分配参数给函数。
函数的参数解释器比较傲慢,它对你提供的参数的信息完全不关心。它只会粗略地将参数进行分割,并且最大限度的进行自动类型转换。事实上,这种类型转换很多时候并不完美。所以最好提前能够对参数进行强类型限制
限制数字类型
下面的函数执行后,会抛出异常
因为 subtract
的参数定义了强类型,参数的类型可能引起函数的处理结果改变。
1 | function subtract([int]$value1,[int]$value2) |
限制日期类型
函数的参数解释器会自动尝试将字符串转换成日期类型,如果转换失败就是抛出异常
看下面的例子
1 | function DayOfWeek([datetime]$date) |
Switch 参数
Powershell
函数最简单的参数类型为布尔类型,除了使用 Bool
类型,也可以使用 Switch
关键字。
下面的函数逆转字符串,但是可以通过 $try
参数进行控制,如果没有指定 $try
的值,默认值为 $false
1 | function tryReverse( [switch]$try , [string]$source ) |
指定函数的返回值
一个或多个返回值
PowerShell
不像其它的编程语言,它的函数可以有多个返回值。如果你直接调用函数,返回值会在控制台输出。当然你也可以将结果存储在一个变量中进一步处理
下面的例子演示返回一个值:
1 | function Square([double]$num) |
下面的例子演示返回多个值
1 | function gbMeasure($amount) |
总结一下,如果一个函数返回一个值,像其它编程语言一样,这个值包括它的类型信息会直接返回。但是如果遇到多个返回值,PowerShell会将所有的返回值自动构造成一个对象数组。
可以通过索引访问数组
Return语句
Powershell
会将函数中所有的输出作为返回值,但是也可以通过return语句指定具体的返回值。
Return 语句会将指定的值返回,同时也会中断函数的执行,return后面的语句会被忽略
看一个例子
1 | function test($num) |
访问返回值
一个函数返回了一个值还是多个值,是可以验证的。下面的例子会产生随机数,如果没有指定个数,默认会返回一个随机数,否则会返回指定个数的随机数
1 | function lottery([int]$number=1) |
从函数的返回值中消除输出
函数默认会将函数中的所有输出作为函数的返回值返回,这样很方便。但有时可能会将不必要的输出误以为返回值。写脚本程序时,可能需要自定义一些函数,这个函数可能只需要一个返回值,但是为了提高函数的可读性,可能会在函数增加一些注释输出行,或者使用write-host
1 | function Test() |
恭喜你!到此 PowerShell
基础入门算是完成了!
之后将介绍 PowerShell
的进阶使用
附录
PowerShell Math类常用函数表
函数名 | 调用写法 | 所在类 | 重载 | 描述 | 参数 |
---|---|---|---|---|---|
sin | [math]::sin(x) | System.Math | 1 | 返回x弧度的正弦值 | double |
cos | [math]::cos(x) | System.Math | 1 | 返回x弧度的余弦值 | double |
abs | [math]::abs(x) | System.Math | 7 | 返回x的绝对值 | 所有数值型 |
sqrt | [math]::sqrt(x) | System.Math | 1 | 返回x的平方根 | double |
pow | [math]::pow(x,n) | System.Math | 1 | 返回x的n次幂 | 两参数都是double |
log | [math]::log(x) | System.Math | 1 | 返回x的自然对数 | double |
log | [math]::log(x,n) | System.Math | 1 | 返回x的以n为底的对数 | double |
min | [math]::min(x,y) | System.Math | 11 | 返回x,y中的最小值 | 所有数值型 |
max | [math]::max(x,y) | System.Math | 11 | 返回x,y中的最大值 | 所有数值型 |
floor | [math]::ceiling(x) | System.Math | 2 | 返回x向下取整的结果 | double、decimal |
ceiling | [math]::ceiling(x) | System.Math | 2 | 返回x向上取整的结果 | double、decimal |
math 类其他函数及详细用法参见微软文档: Math类 |