我有一个CSV文件,其中某些单元格包含多行。我将使用这些数据来比较从powershell获得的值。
这将返回对象之间的差异,但是值是相同的。
预期结果应不返回任何内容,因为两个值相同。
CSV内容:
Value System\CurrentControlSet\Control\ProductOptions System\CurrentControlSet\Control\Server Applications Software\Microsoft\Windows NT\CurrentVersion
代码:
PS> $data = Import-Csv .\tr.csv
PS> $data.Value
System\CurrentControlSet\Control\ProductOptions
System\CurrentControlSet\Control\Server Applications
Software\Microsoft\Windows NT\CurrentVersion
PS> $regval = ((Get-ItemProperty HKLM:\SYSTEM\CurrentControlSet\Control\SecurePipeServers\winreg\AllowedExactPaths).machine | Out-String).Trim()
PS> $regval
System\CurrentControlSet\Control\ProductOptions
System\CurrentControlSet\Control\Server Applications
Software\Microsoft\Windows NT\CurrentVersion
PS> Compare-Object $data.Value $regval
System\CurrentControlSet\Control\ProductOptions... =>
System\CurrentControlSet\Control\ProductOptions... <=
PS> $Tostring = ($data.Value | out-string).Trim()
PS> Compare-Object $Tostring $regval
InputObject SideIndicator
----------- -------------
System\CurrentControlSet\Control\ProductOptions... =>
System\CurrentControlSet\Control\ProductOptions... <=
PS> $Tostring.Length
145
PS> $regval.Length
147
答案 0 :(得分:3)
此帖子不再直接回答OP的问题,而是提供有助于类似情况的背景信息。通过在比较数据之前处理CR和LF字符可以解决此特定问题。有关详细信息,请参见Marked Answer。
由于在这种情况下$@"(?<![\w.]){Regex.Escape(numberToReplace.ToString())}(?![\w.])"
是一个具有名为$data
的属性的对象,可以保存您的数据,因此您需要将value
属性中存储的内容与{{1} }:
value
$regval
是一个字符串数组,在之前是将其通过管道传递到Compare-Object $data.value $regval
的地方。在管道之后,它成为一个字符串对象。在传递到$regval
之前,请参见下面的类型信息。
Out-String
Out-String
是一个对象数组(PSCustomObjects),每个对象都有一个名为$regval.gettype().fullname
System.String[]
的属性,如果需要其数据,则需要直接引用该属性:
$data
为了使用Value
比较两个对象的数据,当对象是相同类型的集合时,似乎会出现最好的结果。在某些情况下,例如$data.gettype().fullname
System.Object[]
$data | Get-Member
TypeName: System.Management.Automation.PSCustomObject
Name MemberType Definition
---- ---------- ----------
Equals Method bool Equals(System.Object obj)
GetHashCode Method int GetHashCode()
GetType Method type GetType()
ToString Method string ToString()
Value NoteProperty string Value=System\CurrentControlSet\Control\ProductOptions
($regval | Get-member).where({$_.MemberType -eq "Property"})
TypeName: System.String
Name MemberType Definition
---- ---------- ----------
Length Property int Length {get;}
,PowerShell会在后台自动进行转换。也许这与值类型有关,因为我不确定。我会在之前 将转换为不同类型的数据进行比较。然后,如果您引用Compare-Object
的{{1}}属性,则该条件变为true:
Compare-Object "1" 1
有关PowerShell如何处理数组类型的更多信息,您可以参考MKlement0's Explanation。
答案 1 :(得分:1)
最可能的解释是:
Out-String
应用于了数组字符串的em>。最直接的解决方法是删除CR字符。来自$regval
(您可以在PowerShell中使用"`r"
生成CR字符):
# ...
# Remove all CRs from $regval.
# Note that not providing a replacement string (missing 2nd RHS operand)
# default to the empty string, which effectively *removes* what was matched.
$regval = $regval -replace "`r"
# Should now work as expected.
Compare-Object $data.Value $regval
说:
由于您只比较两个字符串对象,因此可以避免Compare-Object
的开销,而只需使用-eq
:
$data.Value -eq $regVal
或者,您可以将多行值拆分为行数组,然后分别进行比较。请注意,如果您使用正则表达式"`r?`n"
或('\r?\n'
)来匹配换行符以分隔-匹配仅LF和CRLF换行符,则无需删除CR字符。首先,甚至将Out-String
应用于Get-ItemProperty HKLM:\...
调用的数组输出;但是,使用问题中的变量值,您可以使用:
# Newline-style-agnostic
Compare-Object ($data.Value -split "`r?`n") ($regval -split "`r?`n")
# Or, knowing that $data.Value has LF, and $regval CRLF
Compare-Object ($data.Value -split "`n") ($regval -split "`r`n")
# Or, by using the [string[]] array of registry values directly:
$regvals = (Get-ItemProperty HKLM:\SYSTEM\CurrentControlSet\Control\SecurePipeServers\winreg\AllowedExactPaths).machine
Compare-Object ($data.Value -split "`n") $regvals
关于您尝试过的事情:
$Tostring = ($data.Value | out-string).Trim()
如果$data.Value
是一个没有 trailing 换行符的单字符串-是否已嵌入 换行符-以上是有效的无操作:
Out-String
通过原样传递。Out-String
确实附加了CRLF换行符(在Windows上),但随后的.Trim()
调用再次将其删除。