Powershell Tricky
0.帮助
get-command 获取所有命令
xxx -? 查看帮助, 比如dir -?
get-help xxx -examples 查看例子
查看某个类的成员
xxx | get-member
查看结果:
列表显示
xxx | ft -a
单个显示
xxx | fl
1.系统cmdlet返回值
系统cmdlet,比如ls,返回值类型和结果数量有关.
有多条, 是array; 有一条, 是具体的类型; 没有, 是$null
所以, 如果要取结果的第1条这样的操作, 必须@(ls), 把结果转成array
如果多维数组只有1个元素的情况会出现降维.
如果要用foreach,for循环也要考虑这个问题, 但是foreach-object不用
可以使用.Net容器来避免这个问题
$a = New-Object "System.Collections.Generic.Dictionary[System.Int32,System.Int32]"
$b = New-Object "System.Collections.Generic.List[System.Int32]"
2.foreach-object (%)
在%的{}块中调用continue会直接跳出去(作用于外面一层的循环), 相等于break了, 这是因为%不是真的循环, 而是一个cmdlet
这里必须用return来达到continue的语义, 而break的语义很难在这里实现.
3.作用域
local: 默认的作用域, 可以被里面调用的函数所访问
private: 局部变量, 不能被里面调用的函数所访问
global: 全局变量, 据说能跨脚本, 应该是一个session内都有效
script: 脚本内有效, 也可以被里面调用的函数所访问
一个函数体内继承了上一级调用的作用域, 除了private
也就是说即使不用参数传递, 也可以访问local,global,script的变量.
但是不能修改reference. 因为访问外面的变量时其实是用by value的方式, 一旦做出修改, 等于声明了一个新的local变量, 屏蔽了对外部变量的访问.
和指针有点类似, 只要不修改指向的内容都可以直接写, 比如$a.Add(...) 都是有效的.
如果要修改外部的值只要加上作用域就可以, 比如$script:a = ...
4.函数调用
调用的时候不能用f($a,$b,$c) 或者 f $a,$b,$c的方式, 逗号会被认为是array element的分隔符
必须用f $a $b $c 或者 f -param1 $a -param2 $b -param3 $c类似的形式, 因为script本质上还是命令行
5.参数传递
默认都是by value, 可以在param里加上[ref]$a来指定使用by reference方式, 访问的时候必须$a.Value, 调用的时候必须([ref]$a)
6.IDE
PowerGUI比Powershell ISE好用很多
7.定义结构体
脚本中不能直接定义类或者结构体, 只能通过一种这样的方式
Function New-XXX
{
param
(
[int]$a = 0,
[int]$b = 0
)
$XXX = New-Object PSObject | Select-Object a, b
$XXX.a = $a
$XXX.b = $b
return $XXX
}
8.foreach循环Hashtable和Dictionary
foreach($b in $a)这样的语句对于Hashtable和Dictionary不行, $b和$a会是一样的
必须要foreach($b in $a.GetEnumerator())
9.单引号和双引号
单引号内的字符串不转义, 如果内部需要单引号, 则连打两个单引号
双引号内的字符串会转义, 如果内部需要双引号, 则连打两个双引号Powershell的转义字符是 ` 就是1的左边,tab的上边.
"$a"这样能直接输出$a的值来, 如果有混杂下划线和$a.b这样的话必须要$($a.b)加一层
10.join-path
join-path会测试路径是否存在, 必须处理好Exception, 不能留到下面操作的时候去