PowerShell - 为什么我的脚本使用默认类字段创建对象?

标签 powershell

在我的脚本中,我试图从文本文件创建 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/

相关文章:

amazon-web-services - 使用 PowerShell Core 上传到 Amazon S3 存储桶

shell - Powershell 模块和调用文件

javascript - 简化的 Powershell Web 客户端功能让我可以轻松发布表单数据

powershell - PowerShell:如何运行文件夹大小求和?

powershell - Powershell仅在使用参数而不是使用select时返回结果

c# - PowerShell 变量和 C#

.net - Powershell ParseExact()军事时间Convert-DateTime

powershell - Visual Studio 发布管理 - 使用 ps/dsc 部署遇到服务器证书错误

powershell - 在Powershell中复制和重命名具有特定文件名的文件

powershell - 启 Action 业结果为 "The background process reported an error with the following message: ."