Powershell大印象系列3: 解惑,真相?补充一下

这个文章主要是把一些Powershell经常让人觉得不习惯的地方,和一些内部处理的方式介绍一下。学一门高级语言,经常会被它的方便,让你觉得云里雾里,不过我喜欢POWERSHELL的原因,是因为它是裸体的(至少是若隐若现),呵呵,哪怕它没有公开它的源代码,但是却把实现的逻辑通过Trace-Command公开了出来。好了,现在正是开始。我比较肤浅,所以说的东西也一样,但是希望有抛砖引玉的伟大作用。

1. Return的作用

    我在想,会不会有人说,"啊?RETURN这么简单都讲?会编程的都知道."但是我还是忍不住,说一下在POWERSHELL的RETURN的不同,一般的语言,"retrun"有终止函数和返回结果的作用.但是在POWERSHELL,RETURN就只有前者.不过这个纯属推测,因为表象让人这样觉得.举个例子:

    function bar { Write-Host "123"

    "567"

    return "234"}

    $result = bar 

    这个时候,Result里面会是什么呢?答案是一个数组,里面有567和234.因此可以推论,"567"这个本来就有返回结果的能力,而RETURN "234"呢?就更像234;retrun的作用。那我们平常要怎样打运行过程的信息出去呢?就要用WRITE-HOST啦。嗯嗯。

 

2. ParameterBinding的真相

    运行这个语句Trace-Command -Name ParameterBinding -PSHost -Expression {Get-Process -Name *sql*}

    结果:

Code

 运行这些语句

$b = (Get-Process explorer)
Trace-Command -Name ParameterBinding -PSHost -Expression {$b | Get-Process }

Code

从两个结果得出的结论:

a. 如果参数需要的是数组,POWERSHELL会自动把你的STRING转成数组

b. Powershell 里面有验证绑定的参数的能力。 [System.Management.Automation.ValidateNotNullOrEmptyAttribute]就是其中一个。

c. 在PIPELINE中,也就是管道中的时候,会把System.Diagnostics.Process装箱到psobject里面,也就所谓的OBJECT,在下个指令从管道中提取的时候,参数绑定到InputObject后(InputObject这个PROPERTY支持的就是PSOBJECT),会做一个类似C#里面的 OBJECT AS System.Diagnostics.Process的操作,把Psobject恢复成PROCESS.然后也是遇到了数组的问题,还是把System.Diagnostics.Process转换到System.Diagnostics.Process[]里面。

d. 一般InputObject都是BY VALUE的,为什么呢?因为,我也不知道。以后知道了补上去。

补充ByPropertyName,证明强扭的程序,还是甜的:

Code

这里有个特别的过程,因为FileInfo和FileInfo的每一个Property都不能MATCH,Get-Content的任意一个ByPropertyName的属性(-literalPath -path,-totalCount....).原理上,上面的语句应该是不通过的。但是在黄色Highlight的地方会发现,在全部属性不符合的时候,居然还是被它绑到了-literalPath的属性。为什么呢?现在先看看literalPath是什么。

-literalPath <string[]>
    Specifies the path to an item. Unlike Path, the value of LiteralPath is used exactly as it is typed. No charact
    ers are interpreted as wildcards. If the path includes escape characters, enclose it in single quotation marks.
     Single quotation marks tell Windows PowerShell not to interpret any characters as escape sequences.(会放到‘’里面,不会转换任何的转义字符)。

好的,然后根据Effective powershell的描述,把那个POWERSHELL的CORE反编译过来发现,
[Alias(new string[] { "PSPath" }),
Parameter(Position = 0, ParameterSetName = "LiteralPath", Mandatory = true, ValueFromPipeline = false,
           ValueFromPipelineByPropertyName = true)]
public string[] LiteralPath { }  意思就是这个LiteralPath还支持一个别的属性,就PSPath。好了,现在问题来了,PSPath又是什么呢,前面有PS开头的,我猜测应该就是PS给一些自定义的属性,像PYTHON一样,可以在存在的对象之上附加一些属性,PSPath就是其中一个。为了提高GET-CONTENT和其他指令配合的可用性,Powershell在很多原来的.net 的类之上,附加了一些属性,PSPath就是附加在上面的属性。相信其他的指令也有类似的情况。有待发现:)

3. @的存在意义

    运行一下语句:$b = (1,3,2,4)

                        $a = (4,2,1)

                        Compare-Object $a $b
                        (Compare-Object $a $b).Length

                        @(Compare-Object $a $b).Length

                        $ret1 = (Compare-Object $a $b)     #PSCustomObject
                        $b.GetType()

                        $ret2 = @(Compare-Object $a $b)   #object[]

    运行的结果相信 已经让你基本明白@是做什么的,可能跟上面绑定的时候,把STRING转化成OBJECT[]一样,也就是把东西转成数组。 

                       

posted @ 2009-03-06 10:01  天天爱晴天  阅读(1949)  评论(1编辑  收藏  举报