PowerShell基础知识
如果要学一门语言, 你就必须对语言的语法, 特性有所了解. 只要对语言的各个环境了解, 才能更好编写, 调式, 部署你的程序. 因此, 教程第二部分将会着重于如下几个方面:
1. PowerShell, Shell, 脚本语言等概念;
2. 参数绑定;
3. 类型转换.
这些基础知识, 希望大家不要轻视, 因为后面的教程将会直接引用这些概念.
首先, 我们先来调查PowerShell中最重要的元素: 命令(Command). 在PowerShell中, 命令分为四类: cmdlet, function, script和native Windows commands. 可能看到这四个英文名称会有些头大, 我们来仔细了解一下.
1. cmdlet
在PowerShell官方blog上, 有篇关于Cmdlets和API的介绍. 因为PowerShell建立在.Net上, 再加上COM, WMI, ADO, XML等技术. 使得PowerShell对于.Net应用开发人员,服务器管理人员来说都会非常方便, 通过这些已有的接口, 即可完成大量的任务. 但是, PowerShell的设计者明确的指出Cmdlets是PowerShell的灵魂.
Cmdlet是Command-Let的缩写. cmdlet这类命令有一种统一的命名方法: Verb-Noun, 也就是 动词-名词. 如果你是一名.Net程序员, 那么编程规范中应该也会提出, 对于方法(method)的命名, 最好使用动词-名词形式配合骆驼(Camel)命名法.
查看有哪些cmdlet参考如下:
PS C:\> get-command -CommandType cmdlet
CommandType Name Definition
----------- ---- ----------
Cmdlet Add-Content Add-Content [-Path] <String[]> [-Value] <Object[...
Cmdlet Add-History Add-History [[-InputObject] <PSObject[]>] [-Pass...
Cmdlet Add-Member Add-Member [-MemberType] <PSMemberTypes> [-Name]...
Cmdlet Add-PSSnapin Add-PSSnapin [-Name] <String[]> [-PassThru] [-Ve...
Cmdlet Clear-Content Clear-Content [-Path] <String[]> [-Filter <Strin...
Cmdlet Clear-Item Clear-Item [-Path] <String[]> [-Force] [-Filter ...
Cmdlet Clear-ItemProperty Clear-ItemProperty [-Path] <String[]> [-Name] <S...
这里我省略了绝大部分的显示(^^), PowerShell Version 1.0 微软官方发布的版本包含了
PS C:\> (get-command -CommandType cmdlet).count
129
129确实有点多, 但是实际上在学习过程中你会发现学习他们的过程比你学习unix shell中命令更加容易些, 原因稍后为你解答.
cmdlet是可以进行扩展的, 如果你想开发自己的cmdlet, 你需要下载PowerShell SDK. 目前, 我只知道该 SDK 包含在了Windows Vista Platform. SDK中. 下载该 SDK, 需要进行正版验证. 在伴随着教程的编写过程, 我也会阅读PowerShell SDK中关于PowerShell的介绍, 并尽量用最简单的语言将需要注意的内容, 传达给大家.
cmdlet的开发并不复杂, 可以使用C#作为实现语言, PowerShell SDK已经实现了好了cmdlet的一个基类, 开发的cmdlet只需要继承该基类. 通过这种开发模式, 最大的优点:
(1). 所有的cmdlet中包含了一些公共参数(common parameters), 例如: -Verbose, -Debug, -ErrorAction, -ErrorVariable, and -OutVariable. 这些参数大多用于一些脚本调试等.
(2). 所有的cmdlet中的参数(parameters)具有相似的参数, 相同的类型, 甚至具有相同的性质. 对于接受输入的某些cmdlet来说, 输入的参数就叫做-InputObject, 参数类型一般是[object[]], 而通常都会具有从管道线读取处理对象的属性.
这种一致性带来的最大好处就是, 对于一个命令, 往往你只需要关注命令的特性, 不需要记住复杂繁多的参数. 如果你熟悉unix shell下的utils core tools那么我相信, 例如awk使用-F指定一个支持正则表达式的与分隔符, cut使用-d来分割, sort使用-t进行分割对你来说是痛苦的. 在PowerShell中, 你甚至不需要对cmdlet产生的输出进行分割. 这点你会在稍后看到.
cmdlet编译后的结果不是可执行文件, 而是dll文件, PowerShell启动时, 将这些命令加载, 这些命令执行效率最高, 因为他们在PowerShell时被载入PowerShell进程内.
2. 函数(function)
函数, 准确的说就是: 有名称的代码块(scriptblock). 下面就是一个简单的函数定义:
PS C:\> function Get-DayToBeiJingOlympic
>> {
>> ([datetime] "2008-08-08" - [datetime]::Now).Days;
>> }
>>
PS C:\> Get-DayToBeiJingOlympic
370
细节大家可以不用关心, 稍后都会讲到. 函数就是一段你输入到PowerShell的命令集合.
但是函数在被定义后, 才存在于PowerShell内存中, 当PowerShell退出时, 就会消失.
效率上, 函数在第一次调用时需要编译, 因此第一次调用速度较慢.
3. 脚本(script)
PowerShell在交互式Shell(interactive Shell)和脚本语言(script. Language)之间进行了平衡, 提供了执行脚本的能力. 脚本类似于函数, 存放在文件中, 调用时由PowerShell载入内存, 编译并执行.
效率上来讲, 脚本慢于函数(function), 主要原因在于函数只会在第一次调用时被编译, 而脚本每次调用都会被编译一次. 但是编译后的执行阶段, 他们的性能是近似相等的.
4. native Windows command
我不知道应该这个东西用什么名字. 这类命令在Windows世界大量存在, 譬如: dir, findstr, del, ping. 这些命令就是Windows之前的可执行文件(非.Net命令行可执行文件). 在PowerShell中调用这些命令效率是最低的, 因为执行他们PowerShell需要创建一个新进程. 此外因为这些命令早于PowerShell, 因此他们的信息输出都是基于文本的(也可以说是字符串), 因此丧失了PowerShell对对象的处理能力. 因此, 如果你知道PowerShell的实现, 就避免使用这些命令.
讨论完命令, 我简单介绍下别名(alias):
PS C:\> (Get-Command -CommandType alias).count
101
你一定在想, PowerShell为什么提供了这么多别名, 难道要累死我们??
PowerShell为了方便使用windows和unix, linux的人们, 支持了两套别名, 譬如dir相对于ls, 还有unix, linux的grep等. 这样无论你使用windows还是linux都能相对来说快速的上手PowerShell.
PowerShell Version 1.0中有一个缺陷, 既定义别名时, 不允许指定参数. 这无疑是PowerShell的一个缺陷. 但是因为cmdlet中参数较少(一般都是10个以内), 因此大多数时候, 你不需要定义带有参数的别名, 如果真的需要, 可以用函数来替代. 这种缺陷, 与代码块的执行等功能有冲突. 希望在后续版本能有别名功能能够更加强大.
写在最后:
如果您有幸坚持看了我的啰唆, 我非常的感激. 接下来的3, 4讲也会偏向于概念而非更多的语法. 任何事, 请相信你对解释器行为的理解, 对语言的特性的理解, 都会让你在编写该语言代码时受益匪浅. 因此, 请坚持, 努力的去学习. 我希望在这份漫长教程过程中, 带给大家更多计算机历史, 发展; 不同语言, 技术的对比; 编写健壮代码(无论是像C, C#还是像sh, PowerShell)的思路. 在03, 04中, 我会介绍两个关键核心的概念(算法??), 参数绑定和类型转换.
学习一门语言, 还能学到编程的心得, 这也是我希望的.