Powershell 比较两个文本文件并将差异写入文本文件

Powershell 比较两个文本文件并将差异写入文本文件,powershell,compare,compareobject,Powershell,Compare,Compareobject,我想比较两个文本文件并在另一个文本文件中输出差异 $Location = "c:\temp\z.txt" compare-object (get-content c:\temp\hostname_old.txt) (get-content c:\temp\hostname_new.txt) | format-list | Out-File $Location 主机名\u old.txt server02 server05 server04 server06 server01 主机名\u ne

我想比较两个文本文件并在另一个文本文件中输出差异

$Location = "c:\temp\z.txt"
compare-object (get-content c:\temp\hostname_old.txt) (get-content c:\temp\hostname_new.txt) | format-list | Out-File $Location
主机名\u old.txt

server02
server05
server04
server06
server01
主机名\u new.txt

server04
server01
server02
结果

InputObject   : server05
SideIndicator : <=

InputObject   : server06
SideIndicator : <=
注意:一个输入文件中有重复条目的相关问题是本文的主题。

更新:提供了最佳解决方案。
对于将成员枚举与管道使用进行对比,讨论输出格式,以及将
输出文件
设置内容
进行对比,这个答案可能仍然有意义


在PSv3+中,您可以使用提取
。InputObject
值:

PS> (Compare-Object (Get-Content old.txt) (Get-Content new.txt)).InputObject
server05
server06
注:

  • 成员枚举既方便又快速,但会以内存消耗为代价,这对于非常大的集合(此处不适用)可能是一个问题。
    比较对象
    的输出必须作为一个数组整体收集在内存中(
    [Object[]]
    ),类似地,
    .InputObject
    属性值作为数组返回

  • 对于较慢但内存友好的流式处理(逐个处理),请使用管道和
    选择对象-ExpandProperty
    ,如中所示

重新保存到文件:通过管道将
输出到文件$location
(或者更简洁地说,使用输出重定向:
$location
)就足够了-不需要
格式列表

通常,请注意,
Format-*
cmdlet的目的是生成用于显示的输出,而不是用于编程处理和持久化

这就是说,
输出文件
/
(有效地)在后台使用
格式-*
cmdlet生成输入对象的字符串表示形式
,就像默认控制台输出一样,这就是为什么它不是用于持久化任意输入对象的正确命令。

但是,将
输出文件
/
与字符串一起使用是安全的,因为它们是按原样输出的。相比之下,如果偶数有小数位,则会出现问题,因为它们是使用当前区域性的小数分隔符字符串化的(例如,
,而不是在某些区域性中使用

如果输入对象是字符串,您也可以使用
设置内容
,这比
输出文件
/
快,但需要注意的是,在Windows PowerShell中,默认情况下使用的字符编码不同:
输出文件
/
默认情况下生成UTF-16LE文件,而
Set Content
使用传统系统语言环境的“ANSI”代码页(通常为单字节8位编码,如Windows-1252)。
相比之下,在PowerShell Core中,两个cmdlet都会生成无BOM的UTF-8


请注意,
设置内容
,与
输出文件
不同,只需对非字符串对象调用
.ToString()
方法即可对其进行字符串化。

我猜您正在查找
选择对象-ExpandProperty InputObject

compare-object (get-content c:\temp\hostname_old.txt) (get-content c:\temp\hostname_new.txt) | Select-Object -ExpandProperty InputObject | Out-File $Location
请注意,在将数据写入文件之前,不能在
管道中使用
格式列表

只需使用:


完全符合您的要求。

固溶体。请注意,您可以将
格式-*
cmdlet与
输出文件一起使用(但不能与
设置内容一起使用)。事实上,
Out File
/
(有效地)在幕后使用
格式-*
cmdlet生成输入对象的字符串表示。也就是说,除非输入对象是字符串,否则生成的表示只适合人类使用,而不是作为编程处理的稳定格式。此解决方案不关心重复。每一行新文本都被认为是唯一的。因此,“新”文件中的副本将被复制到“旧”文件中,除非它也在“旧”文件中复制。
compare-object (get-content c:\temp\hostname_old.txt) (get-content c:\temp\hostname_new.txt) | Select-Object -ExpandProperty InputObject | Out-File $Location
compare-object (get-content c:\temp\hostname_old.txt) (get-content c:\temp\hostname_new.txt) -PassThru | Out-File $Location