2

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

$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

主机名_old.txt

server02
server05
server04
server06
server01

主机名_new.txt

server04
server01
server02

结果

InputObject   : server05
SideIndicator : <=

InputObject   : server06
SideIndicator : <=

这就是我想要的:(摆脱 InputObject 和 SideIndicator)

server05
server06

注意:一个输入文件具有重复条目的相关问题是此问题的主题。

4

3 回答 3

1

只需使用-PassThru 参数

compare-object (get-content c:\temp\hostname_old.txt) (get-content c:\temp\hostname_new.txt) -PassThru | Out-File $Location

做你想要的。

于 2019-02-07T11:19:46.037 回答
0

更新Palle Due 的有用答案提供了最佳解决方案。
对于将成员枚举与管道使用进行对比、讨论输出格式以及Out-FileSet-Content.


在 PSv3+ 中,您可以简单地使用成员枚举来提取.InputObject值:

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

笔记:

  • 成员枚举方便快捷,但代价是内存消耗,这可能是非常大的集合的问题(不在此处)。的输出Compare-Object必须作为一个整体收集在内存中的数组 ( [object[]]) 中,并且类似地,.InputObject属性值作为数组返回。

  • 对于较慢但对内存友好的流式处理(一对一处理),请使用带有的管道Select-Object -ExpandProperty,如TobyU 的有效解决方案中所示

重新保存到文件:管道到Out-File $location(或更简洁地说,使用输出重定向:)> $location就足够了 - 不需要Format-List.

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

也就是说,Out-File/ >(有效地)Format-*在幕后使用 cmdlet 来生成输入对象的字符串表示,就像默认的控制台输出一样,这就是为什么它不是持久化任意输入对象的正确命令的原因。

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

如果您的输入对象是字符串,您也可以使用Set-Content,它比Out-File/>更快,但需要注意的是,在 Windows PowerShell 中,默认使用的字符编码不同:Out-File/默认情况下>生成 UTF-16LE 文件,而Set-Content使用旧系统区域设置的“ ANSI" 代码页(通常是单字节 8 位编码,例如 Windows-1252)。
相比之下,在 PowerShell Core中,两个 cmdlet 都生成无 BOM 的 UTF-8。

请注意Set-Content,与 不同的是,只需调用它们的方法即可对Out-File非字符串对象进行字符串化。.ToString()

于 2019-02-07T10:48:47.477 回答
0

我猜你正在寻找Select-Object -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

请注意,您不能format-listPipeline将数据写入文件之前使用。

于 2019-02-07T10:56:43.340 回答