Powershell:始终生成空文件(Compare-Object的输出) [英] Powershell: null file always generated (output of Compare-Object)

查看:226
本文介绍了Powershell:始终生成空文件(Compare-Object的输出)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

此问题的最受欢迎答案涉及以下Windows powershell代码(已编辑,以修复错误):

The most popular answer for this question involves the following Windows powershell code (edited to fix a bug):

$file1 = Get-Content C:\temp\file1.txt  
$file2 = Get-Content C:\temp\file2.txt   
$Diff = Compare-Object $File1 $File2  
$LeftSide = ($Diff | Where-Object {$_.SideIndicator -eq '<='}).InputObject  
$LeftSide | Set-Content C:\temp\file3.txt

我总是得到一个零字节的文件

I always get a zero byte file as the output, even if I remove the $Diff line.

为什么输出文件总是为空,如何解决该问题?

Why is the output file always null, and how can it be fixed?

推荐答案

PetSerAl ,正如他通常所做的那样,提供了对该问题发表评论的关键指针:

PetSerAl, as he routinely does, has provided the crucial pointer in a comment on the question:

成员枚举 -访问集合上的成员(属性或方法)并将其隐式应用于每个元素的能力,结果被收集到 > array 引入了在 PSv3 中。

Member enumeration - the ability to access a member (a property or a method) on a collection and have it implicitly applied to each of its elements, with the results getting collected in an array, was introduced in PSv3.

成员枚举不仅富有表现力和方便,而且 更快替代方法

Member enumeration is not only expressive and convenient, it is also faster than alternative approaches.

一个简化的示例:

PS> ((Get-Item /), (Get-Item $HOME)).Mode
d--hs-   # The value of (Get-Item /).Mode
d-----   # The value of (Get-Item $HOME).Mode

应用 .Mode的值集合,由(...)括起来的命令输出会导致。模式属性可在集合中的每个项目上访问,其结果值作为数组返回 (常规PowerShell数组,类型为 [System.Object []] )。

Applying .Mode to the collection that the (...)-enclosed command outputs causes the .Mode property to be accessed on each item in the collection, with the resulting values returned as an array (a regular PowerShell array, of type[System.Object[]]).

注意事项:成员枚举处理结果类似于 pipeline 的数组,这意味着:

Caveats: Member enumeration handles the resulting array like the pipeline does, which means:


  • 如果该数组只有一个单个元素,该元素的属性值直接返回 ,而不是在单个元素数组内:

  • If the array has only a single element, that element's property value is returned directly, not inside a single-element array:

PS> @([pscustomobject] @{foo=1}).foo.GetType().Name
Int32  # 1 was returned as a scalar, not as a single-element array.


  • 如果要收集的属性值为本身数组,则返回 flat 值数组:

  • If the property values being collected are themselves arrays, a flat array of values is returned:

    PS> @([pscustomobject] @{foo=1,2}, [pscustomobject] @{foo=3,4}).foo.Count
    4 # a single, flat array was returned: 1, 2, 3, 4
    


  • 此外,成员枚举仅适用于获取(读取)属性值,不适用于设置(编写)属性值。
    这种非对称性是设计使然,以避免潜在的不必要的批量修改;在PSv4 +中,使用 .ForEach('< property-name',< new-value>)作为最快的解决方法(见下文)。

    Also, member enumeration only works for getting (reading) property values, not for setting (writing) them. This asymmetry is by design, to avoid potentially unwanted bulk modification; in PSv4+, use .ForEach('<property-name', <new-value>) as the quickest workaround (see below).

    此便捷功能不可用,但是:


    • (如果您在 PSv2 上运行)(分类)

    • 如果集合本身有一个具有指定名称的成员,在这种情况下,将应用集合级成员。

    • if you're running on PSv2 (categorically)
    • if the collection itself has a member by the specified name, in which case the collection-level member is applied.

    例如,即使在PSv3 +中,以下内容不执行成员枚举:

    For instance, even in PSv3+ the following does NOT perform member enumeration:

        PS> ('abc', 'cdefg').Length  # Try to report the string lengths
        2 # !! The *array's* .Length property value (item count) is reported, not the items'
    

    情况-通常在 PSv2 中,需要使用其他方法:

    In such cases - and in PSv2 in general - a different approach is needed:


    • 最快 >替代方法,使用 foreach 语句 ,假设整个集合都适合整个内存(即暗示(使用成员枚举)。

    • Fastest alternative, using the foreach statement, assuming that the entire collection fits into memory as a whole (which is implied when using member enumeration).
    PS> foreach ($s in 'abc', 'cdefg') { $s.Length }
    3
    5
    




    • PSv4 + 替代方法,使用收集方法 .ForEach(),也可以对整个集合进行操作:

      • PSv4+ alternative, using collection method .ForEach(), also operating on the collection as a whole:
      • PS> ('abc', 'cdefg').ForEach('Length')
        3
        5
        

        注意:如果适用于输入集合,还可以使用 .ForEach('< prop-name>',< ; new-value>),这是无法使用的最快解决方法。< prop-name> =< new-value> ,即无法通过成员枚举设置属性值。

        Note: If applicable to the input collection, you can also set property values with .ForEach('<prop-name>', <new-value>), which is the fastest workaround to not being able to use .<prop-name> = <new-value>, i.e. the inability to set property values with member enumeration.


        • 最慢​​但内存效率高的方法,使用管道

        • Slowest, but memory-efficient approaches, using the pipeline:

        注意:仅当您单独处理一项而不同时将结果收集到内存中时,使用管道才有效节省内存。

        Note: Use of the pipeline is only memory-efficient if you process the items one by one, in isolation, without collecting the results in memory as well.

        使用 ForEach对象 cmdlet ,如伯特·哈里斯的有用答案

        PS> 'abc', 'cdefg' | ForEach-Object { $_.Length }
        3
        5
        

        对于属性仅(相对于方法),选择对象-ExpandProperty 是一个选项;从概念上讲,它是清晰,简单的,实际上在性能方面与 ForEach-Object 方法相当(有关性能比较,请参见我的答案

        For properties only (as opposed to methods), Select-Object -ExpandProperty is an option; it is conceptually clear and simple, and virtually on par with the ForEach-Object approach in terms of performance (for a performance comparison, see the last section of this answer of mine):

        PS> 'abc', 'cdefg' | Select-Object -ExpandProperty Length
        3
        5
        

        这篇关于Powershell:始终生成空文件(Compare-Object的输出)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆