Powershell学习笔记——变量和命令
变量,伟大的变量
Powershel支持变量,这个功能对用惯了CMD的开发人员来说,那简直就是惊喜——终于可以结束总是把环境变量搞乱的痛苦日子了。
Powershell的变量是以$号作为前缀的,所有变量都必须以$号开头,比如$var1, $my_var_2……。按照惯例,变量名当然是字母数字和下划线的组合。不过Powershell的变量不完全符合惯例——它的变量几乎允许任意字符。不过,当你准备使用“$my var”这个“变量”的时候,你会得到一个错误,因为,对于包含特殊字符的变量名,需要点特别的标记——用一对大括号括起来——当然,如果你不嫌麻烦的话,你也可以用同样的手段来包装一下不含特殊字符的变量名。来看示例:
- PS F:\> $var1 = 1
- PS F:\> ${my var} = 2
- PS F:\> "$var1, ${my var}, ${var1}"
- 1, 2, 1
- PS F:\>
惊喜到这里还未结束。Powershell的变量都是有类型的,因为它们都对应于.NET中的基本数据类型,或者对象。做个实验:
- PS F:\> ${my var}.getType().fullName
- System.Int32
- PS F:\> $var2 = "James Fancy"
- PS F:\> $var2.getType().fullName
- System.String
- PS F:\>
可以看到,刚才定义的${my var}是Int32类型,而新定义的$var2是String类型,而它们的类型,完全是由它们的值决定的,这个,仔细观察一下定义这两个变量的那两条命令就明白了。于是,这里引发一个问题,既然变量是有类型的,那是否可以指定类型呢?答案是肯定的:
- PS F:\> [long] $var3 = 1
- PS F:\> $var3.getType().fullName
- System.Int64
- PS F:\> [string] $var3 = $var3
- PS F:\> $var3.getType().fullName
- System.String
- PS F:\>
这个例子很好的解释了,可以通过前缀由方括符包含的类型名称来为变量指定类型,而且还带出两点惊喜:第一,变量的类型是可以改变的;第二,从长整型到字符串类型可以直接转换而不需要特别的工具或者函数,当然,这还可以扩展到其它类型的转换。
现在我们需要了解一下,常见的类型都有哪些呢?简单的列举一下:bool、char、byte、sbyte、int16、int32或int、int64或long、uint16、uint32、uint64、float或single、double、string、datetime、guid、xml、switch……除此之外,还有另外一些内置的类型,以及.NET库中的所有类和结构——太给力了!
这些内置数据类型之间大多可以自动转换。在表达式中,如果存在混合类型的运算,多数时候是以先出现的那个变量的类型为准来进行运算,比如
- PS F:\> 2 + "2" # 先出现整型,后面的字符串转换为整进行整数运算
- 4
- PS F:\> "2" + 2 # 先出现字符串型,后面的整形转换成字符符进行连接运算
- 22
- PS F:\>
常量和只读变量
变量是有了,Powershell能定义常量么?当然可以,不过需要用new-variable来定义:
- PS F:\> new-variable myConst "James Fancy" -option constant
- PS F:\> $myConst
- James Fancy
- PS F:\>
常量是不能改变的,尝试给它重新赋值会抛出错误。这不是悲剧,悲剧的是,常量不能被删除,就算加上-force参数也不能被删除。
- PS F:\> del -force variable:myConst
- Remove-Item : 无法删除变量 myConst,因为该变量为常量或者为只读变量。如果该变量
- 为只读变量,请指定 Force 选项,然后重试此操作。
- 所在位置 行:1 字符: 4
- + del <<<< -force variable:myConst
- + CategoryInfo : WriteError: (myConst:String) [Remove-Item], Sess
- ionStateUnauthorizedAccessException
- + FullyQualifiedErrorId : VariableNotRemovable,Microsoft.PowerShell.Comman
- ds.RemoveItemCommand
- PS F:\>
不过这个常量并不是永驻于你的操作系统了,只需退出当前控制台,再开启一个新的控制台,你就会发现,一些都是崭新的,没有之前定义的一切东西:函数、变量以及删不掉的常量。
话说回来,如果需要一个可以删除的常量,那不妨考虑下只读变量,只读变量有两种方式产生,一种是跟定义常量一样,在通过new-variable命令定义的时候指定-option为readonly;另一种是在变量已经存在的情况下,改变其选项。
- PS F:\> new-variable rVar "James" -option readonly # 第一种方法
- PS F:\> $rVar2 = "Fancy" # 第二种方法,先定义一个普通变量
- PS F:\> (get-variable rVar2).options = "readonly" # 再通过get-varialbe取得变量对象并改变选项
- PS F:\> # 当然上面这句话也可以用set-varialbe命令来完成,就像这样
- PS F:\> # set-variable rVar2 -option readonly
- PS F:\>
只读变量是可以被删除的,当然需要-force参数。只读变量也可以变回普通变量,只需要改变其选项,当然也需要-force参数。
- PS F:\> del variable:rVar -force # 删除只读变量rVar
- PS F:\> set-variable rVar2 -option none -force # 将rVar2变成普通变量
- PS F:\>
Device, Powershell的命名空间
上面提到变量的时候已经多次使用了“variable:变量名”这种形式的东东。这里的“varialbe:”被称作Device,就好像C:、D:、E:、F:一样。也许理解起来有点困难,不过,把它想像成“命名空间”应该就好理解了。
上面的示例中定义了$var1、$var2、${my var}等变量,其它它们的全称应该是$variable:var1、$variable:var2、${varialbe:my var}。除了variable之外,常用的命名空间还有env、function、alias等。
Powershell的命令
如果想知道Powershell有哪些命令可以用,help已经说明了,可以用get-command来查看。在控制台输入help get-command之后,就可以看到get-command的用法。
在get-command的语法中可以看到一个-CommandType参数,它允许get-command按类型查询命令,其中类型包括Alias、Function、Filter、Cmdlet、ExternalScript、Application和Script。最后一项scrip我没搞懂,不过前面几项分别是:
√ Alias,别名,通过set-alias命令为Cmdlet、Function等命令设置的一个简单易记的名称。
√ Function,函数,你懂的。
√ Filter,一种特别的函数,用于在重定向操作中过滤对象列表。
√ Cmdlet,可以理解为Powershell的内置命令——当然,Powershell的内置命令是可以扩展的。
√ ExternalScript,所有在路径(由$env:path变量的值说明)中的.ps1脚本
√ Application,毫无悬念,路径中的.exe文件(其实应该说是PE文件,因为.dll等也算在内)
Cmdlet
Cmdlet是Powershell的内置命令,比如之前用到的get-command就是一个Cmdlet。按Powershell的规范,Cmdlet的名字都是由动词和宾语构成的,以说明这个Cmdlet的作用,其结构是“动词-宾语”。比如get-command的意思就很明显,是获取命令相关的信息的。
同样,通过help get-command,可以在其说明文档中找到get-command的第二种语法里有一个-verb参数,提供通过动词来查找命令的功能。这里的动词包括get、set、test……很多,而且可以自己定义。比如“get-command -verb go”找不到有匹配的命令,但是如果定义了一个名叫"go-url"的函数之后,再运行“get-command -verb go”就可以将刚定义的“go-url”显示出来了,就像这样:
- PS F:\> get-command -verb go
- PS F:\> function go-url() { "going..." }
- PS F:\> get-command -verb go
- CommandType Name Definition
- ----------- ---- ----------
- Function go-url param()...
- PS F:\>
上面提到Cmdlet是可以扩展的,的确如此。你可以自己按照规范来写DLL扩展Cmdlet,当然那不是一件简单的事情。对于脚本的常规用法来说,它太复杂了,所以我在短期内没准备去学习它。
Alias,别名
我们曾经多次使用help命令,其实它是一个别名——或者说得拟人一点,叫昵称。help是get-help的另一个名字,输入get-help很麻烦,因为它包含8个字符,其中一个还是符号,所以懒人们发明了“别名”,为它取了另一个更简明的名字,help。
当然,并不是只有get-help享受了这个待遇。如果你在控制台中键入alias命令,就可以看到目前已经定义了的所有别名,以及它们对应的原始命令。当然,这里显示的只是已经定义的,如果你愿意,随时可以添加新的别名。比如刚才的示例中定义了一个go-url函数,那么现在为它取个新名字,叫url:
- PS F:\> set-alias url go-url
- PS F:\> url
- going...
- PS F:\>
甚至,还可以为别名指定别名,比如
- PS F:\> set-alias myurl url
- PS F:\> get-alias url,myurl
- CommandType Name Definition
- ----------- ---- ----------
- Alias url go-url
- Alias myurl url
- PS F:\>
这里,get-alias会显示指定的别名列表中每个别名的信息。
如果不想要某个别名了,可以用del命令删除它——哦,del也是个别名,真实的命令是remove-item。
- PS F:\> del alias:url
- PS F:\>