Powershell 变量

    本文主要和大家描述一下关于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

posted @ 2010-11-18 17:26 Sai~ 阅读(...) 评论(...) 编辑 收藏