在我的脚本中,我试图从文本文件创建 PowerShell 对象。这是一个文本文件的示例。
junk data at the
beginning of
the file
Item: Car
In Stock: YES
Make: Ford
Model: Taurus
Color: Blue
Miles: 0
Item: Car
Miles: 0
Item: Truck
Item: SUV
Item: Car
In Stock: YES
Make: Honda
Model: Civic
Color: Red
Miles: 0
junk
data at the
end
有时这些文件的开头和结尾都是垃圾数据。我尝试用我的 Select-String 语句来解决这个问题。这是我的脚本:
[CmdletBinding()]
param(
[Parameter(Mandatory=$true, ValueFromPipeline=$true)]
[string]$File
)
class Item {
[string] $Item = ''
[string] $Found = 'NO'
[string] ${In Stock} = 'N/A'
[string] $Make = 'N/A'
[string] $Model = 'N/A'
[string] $Color = 'N/A'
[string] $Miles = 'N/A'
}
[string[]]$Keep = @("Item:", "In Stock:", "Make:", "Model:", "Color:", "Miles:")
(Get-Content $File | Select-String -Pattern ($Keep -join "|") |
Out-String) -split '(?m)(?=^Item:)' -ne '' -replace '(?m)^(.+?):', '$1=' |
ConvertFrom-StringData | ForEach-Object {
$Obj = [Item] $_
if ($Obj.'In Stock' -eq 'Yes') {
$Obj.Found = 'YES'
}
Write-Output $Obj
}
该脚本的效果比它好得多。非常感谢另一位帮助我走到这一步的用户。当我运行脚本时,我在顶部得到一个 EXTRA 对象,其中包含类中定义的所有默认值。这是为什么?
这是输出:
Item:
Found: NO
In Stock: N/A
Make: N/A
Model: N/A
Color: N/A
Miles: N/A
Item: Car
Found: YES
In Stock: YES
Make: Ford
Model: Taurus
Color: Blue
Miles: 0
Item: Car
Found: NO
In Stock: N/A
Make: N/A
Model: N/A
Color: N/A
Miles: 0
Item: Truck
Found: NO
In Stock: N/A
Make: N/A
Model: N/A
Color: N/A
Miles: N/A
Item: SUV
Found: NO
In Stock: N/A
Make: N/A
Model: N/A
Color: N/A
Miles: N/A
Item: Car
Found: YES
In Stock: YES
Make: Honda
Model: Civic
Color: Red
Miles: 0
最佳答案
您的 ForEach-Object
的输入电话在其中[Item]
cast 发生(见下面的解释)以一个空行开始,这会产生一个额外的输出对象(具有所有类的默认值),因为它的作用类似于 [Item] @{}
(因为类似 "`n" | ConvertFrom-StringData
输出一个空的哈希表),这反过来就像简单地调用(无参数默认)构造函数,[Item]::new()
.
您可以按如下方式避免此空行(注意使用 .Line
并避免调用 Get-Content
以将文件路径直接传递给 Select-String
):
(
(Select-String -Pattern ($Keep -join "|") -LiteralPath $File).Line | Out-String
) -split '(?m)(?=^Item:)' -ne '' -replace '(?m)^(.+?):', '$1=' |
ConvertFrom-StringData | ForEach-Object {
$Obj = [Item] $_
if ($Obj.'In Stock' -eq 'Yes') {
$Obj.Found = 'YES'
}
Write-Output $Obj
}
空行(出现在开头和结尾)的原因是您直接发送 Select-String
的输出对象到 Out-String
,这会产生与您在控制台中看到的相同的显示字符串格式。访问 .Line
属性(property)在 Select-String
的输出对象避免了这种情况,因为它只输出字符串(而不是默认发出的 Microsoft.PowerShell.Commands.MatchInfo
实例),这不添加任何格式。附注:
Out-String
出乎意料地总是在其输出字符串中附加一个尾随换行符; GitHub issue #14444 中讨论了这种有问题的行为.[Item]
的说明类型转换工艺:关于类的实例化
[Item]
,属性具有类定义中指定的默认值,除非您稍后覆盖它们。通过类型转换 hashtable - 作为
ConvertFrom-StringData
的输出- 至 [Item]
,其键与类的属性名称匹配的条目隐式设置这些属性;所有其他人保留其默认值(并且不允许使用与属性名称不匹配的键的条目)。这种通过从哈希表进行转换的构造在 this answer 中有详细说明。 .
带有哈希表文字的简化示例
@{ ... }
:class Item {
$A = 'A_default'
$B = 'B_default'
$C = 'C_default'
}
# Construct an [Item] instance and assign to its .B property
[Item] @{ B = 'B_NEW' }
以上产生:A B C
- - -
A_default B_NEW C_default
关于PowerShell - 为什么我的脚本使用默认类字段创建对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68146796/