本文主要和大家描述一下关于Powershell变量的详细内容,上回和大家聊到了Powershell的远程管理,有朋友反映Powershell的基础只是还不够了解,所以先谈谈在Powershell中的变量问题.
创建自己的变量
PS C:\Users\Terry> $a = 1.2 那么我们就创建了一个名字为a的变量,注意Powershell 中变量都用美元符号"$"做为开始.
PS C:\Users\Terry> $b = 2.3 我们再次创建了一个为b的变量,两个变量是可以直接进行运算的,例如对他们进行一个乘操作.
PS C:\Users\Terry> $a*$b
2.76
很明显的,我们也可以对变量直接进行变量区间的传递赋值:
PS C:\Users\Terry> $c=$a*$b
PS C:\Users\Terry> $c
2.76
当使用字符串变量的时候,这里有一些小的技巧,大家可以注意了:
PS C:\Users\Terry> "`$c=`$a*`$b equals $c"
$c=$a*$b equals 2.76
在字符串""包围的区间要引用变量,可以很简单的,直接"$变量" 来表达我们的变量值,当我们需要转移$或者双引号等特殊字符使用我们通常使用"`"(1旁边那个键).
接下来可以进行更复杂的运算,如果在字符串引用变量进行进一步运算:
比如我们想在字符串中直接显示变量a和变量b的乘积值
PS C:\Users\Terry> "$a*$b"
1.2*2.3
这样是不行的.
通常我们使用
PS C:\Users\Terry> "$($a*$b)"
2.76
来进行一个转换,同理的.
我创建一个数组,然后求他的数组长度
PS C:\Users\Terry> $arr=1,2,3,4
PS C:\Users\Terry> $arr
1
2
3
4
PS C:\Users\Terry> "`$arr array length equals $arr.Length (this is error)"
$arr array length equals 1 2 3 4.Length (this is error)
PS C:\Users\Terry> "`$arr array length equals $($arr.Length) (this is ok)"
$arr array length equals 4 (this is ok)
如果我们的变量名比较复杂,存在空格,或者特殊字符,一般我们直接使用是会出错的,Powershell默认会使用空格或者一些特殊字符作为分解符号(DELIMITER)
比如:
PS C:\Users\Terry> $a b=123
表达式或语句中出现意外标记“b=123”。
所在位置 行:1 字符: 9
+ $a b=123 <<<<
+ CategoryInfo : ParserError: (b=123:String) [], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : UnexpectedToken
这样创建一个$a b 的变量就有问题了.所以要使用{}来对变量名进行一个解析:
PS C:\Users\Terry> ${a b}=123
PS C:\Users\Terry> ${a b}
123
PS C:\Users\Terry> "${a b}"
123
变量返回值
当我们调用一些命令的时候,我们还可以把返回值直接赋予给变量.
比如:
PS C:\Users\Terry> $ret = ls
PS C:\Users\Terry> $ret
目录: C:\Users\Terry
Mode LastWriteTime Length Name
---- ------------- ------ ----
d---- 2010/11/15 10:43 CMB
d-r-- 2010/11/4 19:18 Desktop
d---- 2010/11/18 15:23 Tracing
-a--- 2010/11/16 16:24 11544 a
-a--- 2010/11/13 14:30 21466 function.ps1
PS C:\Users\Terry> $ret.GetType()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True Object[] System.Array
我将枚举目录的结果直接返回给变量$ret,查看$ret的类型是Object[] 数组.
Powershell变量魅力
一键赋值能力:
PS C:\Users\Terry> $a=$b=$c=1
PS C:\Users\Terry> $a
1
PS C:\Users\Terry> $b
1
PS C:\Users\Terry> $c
1
变量交换能力:
PS C:\Users\Terry> $a=1;$b=2
PS C:\Users\Terry> $a,$b=$b,$a
PS C:\Users\Terry> "$a $b"
2 1
使用Powershell还可以非常方便的访问文件
比如我们在c:\根目录下创建一个1.txt 里面随便写入内容
我们可以直接使用
PS C:\Users\Terry> ${c:\1.txt}
123123123
PS C:\Users\Terry> $command = "`${$env:windir\windowsupdate.log}"
PS C:\Users\Terry> Invoke-Expression $command
来查看内部的内容,某些时候,我们可以用来查询windows日志:
这里有一个小技巧,我们直接使用环境变量$env:windir再在外部使用$来打开文件时候是不能正确解析的,他会被当作变量名的文件路径了
所以我们要把调用的命令解析成可执行的方式交给Invoke_Expression 来使用 .
维护Powershell变量
首先是查找变量
可以使用DIR/Get-ChildItem (是Alias对)
PS C:\Users\Terry> dir variable:
Name Value
---- -----
$ $a $b
? True
^ $a $b
_
a 2
a b 123
args {}
arr {1, 2, 3, 4}
b 1
c 1
我们刚才创建的变量就可以看到了.
当然具体的帮助大家可以看看Get-Help Get-ChildItem –Full 看看如果进行-include和-exclude操作.当我们要查找我们的a变量的时候,通常会这样搜索:
存在字符串1的数组行:
PS C:\Users\Terry> dir variable:|Out-String -Stream|Select-String "1"
$ 1
a b 123
arr {1, 2, 3, 4}
b 1
c 1
PID 1396
PROFILE E:\Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1
PSHOME C:\Windows\System32\WindowsPowerShell\v1.0
ReportErrorShowSource 1
text $a*$b={123*0.19}
当我们要验证某个变量是否存在的时候,可以使用Test-Path
PS C:\Users\Terry> Test-Path variable:\a
True
说明变量a是存在.
删除变量:
PS C:\Users\Terry> Remove-Variable -Name a
PS C:\Users\Terry> del variable:\b
PS C:\Users\Terry> $a
PS C:\Users\Terry> $b
使用Remove-Variable 或者是Del 来删除变量.
关于变量操作的 Ps cmd 大家可以直接使用来搜:
PS C:\Users\Terry> Get-Command -Noun Variable
CommandType Name
----------- ----
Cmdlet Clear-Variable
Cmdlet Get-Variable
Cmdlet New-Variable
Cmdlet Remove-Variable
Cmdlet Set-Variable
在Powershell中还存在许多的windows环境变量,$env:*之类的
大家可以看看dir env:来看看系统变量.
最后 Powershell变量的作用域
Powershell 会存在一个作用域,也就是变量在那个作用域下可用.我们需要了解的有4个作用域:
global,private,local,script
我们先看看官方是怎么表述的:
Scope allocation
Description
$private:test = 1
变量只能在当前作用域,脚本,函数可见,不能传递给其他的作用域,同理也只能在当前作用域下读写.
$local:test = 1
变量在本地作用域下创建,这是创建变量的默认作用域,本地作用域变量能够在其他作用域下读取,但是不能通过其他作用域修改,只有本地作用域能够修改.
$script:test = 1
脚本作用域变量只在脚本中有效,他可以在脚本的任何作用域下可见.比如在一个脚本的函数下创建了一个变量,那么在脚本的外部的函数也是可以访问的到的.
$global:test = 1
变量任何作用域下可用,甚至是外部函数和脚本.
我们来做几个测试加强对这个概念的理解:
PS C:\Users\Terry> notepad test.ps1
我们先打开一个测试的脚本test.ps1在里面输入:
$windows = $env:windir
"Windows Folder: $windows"
保存关闭以后,执行
PS C:\Users\Terry> Set-ExecutionPolicy RemoteSigned
执行策略更改
执行策略可以防止您执行不信任的脚本。更改执行策略可能会使您面临 about_Execution_Policies
帮助主题中所述的安全风险。是否要更改执行策略?
[Y] 是(Y) [N] 否(N) [S] 挂起(S) [?] 帮助 (默认值为“Y”): y
我们的Powershell默认是不允许执行没有签名的脚本,所以我们设置成RemoteSigned.允许本地未签名脚本.
PS C:\Users\Terry> $windows = "Hello"
PS C:\Users\Terry> & .\test.ps1
Windows Folder: C:\Windows
PS C:\Users\Terry> $windows
Hello
(小技巧,执行脚本的时候,要使用&或者. 路径的方式)
我们首先在当前作用域下创建 windows 变量,然后调用脚本,脚本复制为 c:\windows,执行完脚本以后,windows变量还是Hello
再来回顾一下我们当时的定义:
变量在本地作用域下创建,这是创建变量的默认作用域,本地作用域变量能够在其他作用域下读取,但是不能通过其他作用域修改,只有本地作用域能够修改.
我们修改test.ps1在顶部加上:$windows 增加一个打印,再次执行:
PS C:\Users\Terry> $windows = "Hello"
PS C:\Users\Terry> & .\test.ps1
Hello
Windows Folder: C:\Windows
PS C:\Users\Terry> $windows
Hello
也证实了,官方的定义.只能读取不能修改.
关于Global 没有太多想解释的..$global:test=1创建就好了(这里强调一个,所有变量都 只对当前Session有效,也就是一个Powershell进程)
那么我们来看看private变量
PS C:\Users\Terry> $private:a=1
PS C:\Users\Terry> $a
1
PS C:\Users\Terry> function test{$a}
PS C:\Users\Terry> test
没有任何输出,说明private 是不能跨域的
我们修改刚才的test.ps1更新内容为$a
PS C:\Users\Terry> $private:a = 1
PS C:\Users\Terry> notepad .\test.ps1
PS C:\Users\Terry> . .\test.ps1
1
PS C:\Users\Terry> & .\test.ps1
细心的读者可能发现了,使用&和.调用脚本是不同的.
&的话,是会重新开打脚本的Scope,而.只作为本地Scope 当前Scope来执行脚本的.
Script变量,大家可以自己测试啦,其实都很简单的.
Powershell强类型变量
Powershell是基于.NET 类型来使用的,.NET 我们知道是使用的强类型,意味着,我们在PS中可以使用同样强大的强类型变量
PS C:\Users\Terry> [DateTime]$d = "1"
无法将值“1”转换为类型“System.DateTime”。错误:“该字符串未被识别为有效的 DateTime。”
所在位置 行:1 字符: 13
+ [DateTime]$d <<<< = "1"
+ CategoryInfo : MetadataError: (:) [], ArgumentTransformationMetadataException
+ FullyQualifiedErrorId : RuntimeException
PS C:\Users\Terry> [Int]$i = 1
PS C:\Users\Terry> $i="1"
PS C:\Users\Terry> $i ="a"
无法将值“a”转换为类型“System.Int32”。错误:“输入字符串的格式不正确。”
所在位置 行:1 字符: 3
+ $i <<<< ="a"
+ CategoryInfo : MetadataError: (:) [], ArgumentTransformationMetadataException
+ FullyQualifiedErrorId : RuntimeException
使用强类型变量,可以做进一步执行前的类型确认.
只读或只写其他功能的变量大家可以参考这个连接了,这些功能一般相对来说用的比较少.
参考Link:http://powershell.com/cs/blogs/ebook/archive/2008/10/22/chapter-3-variables.aspx