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

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

问题描述

这个问题的最流行答案 涉及以下 Windows powershell 代码(已编辑以修复错误):

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

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

我总是得到一个零字节文件作为输出,即使我删除了 $Diff 行.

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:

成员枚举 - 访问集合上的成员(属性或方法)并将其隐式应用于它的每个元素,结果被收集在一个数组中,是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 应用到 (...) 封闭命令输出的 collection 导致 .Mode每个项目上访问的 code> 属性,结果值以数组形式返回(常规 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[]]).

注意事项:成员枚举像管道那样处理结果数组,这意味着:

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).

    这个方便的功能不可用,但是:

    This convenient feature is NOT available, however:

    • 如果您在 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>set 属性值.),这是无法使用 的最快解决方法.= <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-Object cmdlet,如 Burt Harris 的帮助答案:

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

        仅对于属性(而不是方法),Select-Object -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):

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

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

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