【问题标题】:Using ConvertFrom-String with value that are not present in all sets of data将 ConvertFrom-String 与所有数据集中不存在的值一起使用
【发布时间】:2019-01-10 20:51:40
【问题描述】:

我有一个包含结构化数据的文本文件(类似于 Json),我想用 ConvertFrom-String 解析它以提取部分数据。我无法更改文件中数据的结构方式,因此我必须按原样处理它们。

这是数据示例。完整的文件包含更多这些块,并且每个块的“属性”都比我在这里展示的要多(保持小而易读:-))。请注意,第三个块为 icon 属性,其他项目没有。

$Data = @'
    c_first_item = {    
        time = 270  
        category = cat_red
        min_value = {
            int = 10
        }
        max_value = {
            int = 20
        }
    }

    c_second_item = {   
        time = 270
        category = cat_blue
        min_value = {
            float = 10
        }
        max_value = {
            float = 20
        }
    }

    c_third_item = {    
        time = 270
        icon = c_third_icon
        category = cat_red
        min_value = {
            int = 10
        }
        max_value = {
            int = 20
        }
    }
'@

这是 ConvertFrom-String 使用的我的模板。

    $Template = @'
    {Name*:c_first_item} = \{   
        time = 270

        category = {Category:cat_red}


        random_property = \{
            random_property_value = 10
        \}

        random_property = \{
            random_property_value = 20
        \}
    \}

    {Name*:c_second_item} = \{
        time = 100
        icon = {Picture?:c_third_icon}

        category = {Category:cat_blue}

        random_property = \{
            random_property_value = 10
        \}

        random_property = \{
            random_property_value = 20
        \}
    \}
'@  

我用ConvertFrom-String 运行这段代码来解析我想要的数据:

$Result = $Data | ConvertFrom-String -TemplateContent $Template

预期的结果应该是这样的:

Name          Category  Picture
----          --------  -------
c_first_item  cat_red   
c_second_item cat_blue
c_third_item  cat_red   c_third_icon

但我却得到了这个:

Name          Category
----          --------
c_first_item  cat_red   
c_second_item cat_blue
c_third_item  cat_red  

如您所见,我的输出对象中没有Picture 属性,因为ConvertFrom-String 无法根据我的要求解析数据。我想我给出的例子不足以教算法如何反应。

有没有办法让我教ConvertFrom-String 为不存在icon 的块获取一个空的Picture 属性?


更新:1 月 25 日

根据@iRon 的要求,这是一个将Length 属性添加到结果的示例。

首先,我正在解析的文件(Test.txt):

d_mem_towers_sulfuric_forest = {
    is_for_colonizeable = yes
    category = deposit_cat_rare

    icon = d_radioactive_wasteland

    resources = {
        category = planet_deposits
        produces = {
            society_research = 4
            energy = 4
        }
    }

    planet_modifier = {
        planet_jobs_energy_produces_mult = 0.10
        planet_jobs_society_research_produces_mult = 0.10
        planet_max_districts_add = -1
        pop_environment_tolerance = -0.15
    }

    drop_weight = {
        weight = 0
    }
}

然后,模板文件(Template.txt):

{Object*:{Name:d_mem_sadrell_capital} = \{
    is_for_colonizeable = yes
    category = {Category:deposit_cat_rare}

    icon = {Picture:d_building}

    planet_modifier = \{
        planet_housing_add = 3
        pop_environment_tolerance = 0.1
        planet_jobs_specialist_produces_mult = 0.15
    \}

    triggered_planet_modifier = \{
        potential = \{
            exists = owner
            owner = \{ is_regular_empire = yes \}
        \}
        modifier = \{
            job_researcher_add = 2
            job_clerk_add = 2
        \}
    \}

    triggered_planet_modifier = \{
        potential = \{
            exists = owner
            owner = \{ is_hive_empire = yes \}
        \}
        modifier = \{
            job_brain_drone_add = 2
            job_maintenance_drone_add = 2
        \}
    \}

    triggered_planet_modifier = \{
        potential = \{
            exists = owner
            owner = \{ is_machine_empire = yes \}
        \}
        modifier = \{   
            job_calculator_add = 2
            job_maintenance_drone_add = 2
        \}
    \}

    drop_weight = \{
        weight = 0
    \}
\}}

{Object*:{Name:d_mem_sadrell_industrial_complex} = \{
    is_for_colonizeable = yes
    category = {Category:deposit_cat_rare}

    icon = {Picture:d_crater}

    planet_modifier = \{
        pop_environment_tolerance = -0.1
        planet_jobs_minerals_produces_mult = 0.25
        district_mining_max = 4
    \}

    drop_weight = \{
        weight = 0
    \}
\}}

{Object*:{Name:_mem_strange_mountain} = \{
    time = 365
    is_for_colonizeable = yes
    category = {Category:deposit_cat_blockers}

    icon = {Picture:d_mem_strange_mountain}

    resources = \{
        category = deposit_blockers
        cost = \{
            energy = 1000
            minerals = 1000
        \}
    \}

    drop_weight = \{
        weight = 0
    \}
\}}

最后,这是我用来提取数据的一段代码:

$testText = Get-Content  -Path "Path\to\text.txt" #MEM
$template = 'Path\to\template.txt'

$result = $testText |
    ConvertFrom-String -TemplateFile $template |
    Select-Object -ExpandProperty Object |
    Union-Object

$result

预期的结果应该是这样的:

Name                         Category         Picture               
----                         --------         -------        
d_mem_towers_sulfuric_forest deposit_cat_rare d_radioactive_wasteland

但我得到了这个:

Name                         Category         Picture                 Length
----                         --------         -------                 ------
d_mem_towers_sulfuric_forest deposit_cat_rare d_radioactive_wasteland
                                                                      0

我的对象的第二行包含我不解析的Length 属性,所以我猜它以某种方式来自Union-Object

有什么想法吗?

【问题讨论】:

  • 试试:$Result |Union-Object
  • @iRon :这个函数无法帮助我得到解析不首先返回的结果。或者有什么我不明白的。 :)
  • 更新:1 月 25 日开始解决问题:从 $Result 中删除 | Union-Object。而是将其转换为 JSON ($Result | ConvertTo-Json) 或 PowerShell 表达式 ($Result |ConvertTo-Expression) 并注意流末尾的空字符串。这是导致结果中长度属性类似于:"" | Union-Object(另请参见:"" | Get-Member -Type Property)的原因。
  • 您还可以通过$result | %{$_.GetType()} 查看不同的输出类型。无论如何,解决方案是仅包含包含某些内容的对象 (... | Where-Object {$_} | Union-Objec) 或仅从对象列表中排除字符串 (... | Where-Object {$_ -isNot [String]} | Union-Object)。
  • 感谢您抽出宝贵时间@iRon。看起来SelectFrom-String 以某种方式生成了不需要的数据。我会按照你的建议简单地过滤它们,这样它们就不会再打扰我了。 :)

标签: powershell


【解决方案1】:

虽然您的所有属性(包括Picture)都在$Result 对象中,但它们不会输出(显示),因为并非所有(尤其是第一个)对象都包含Picture 属性(请参阅相关的问题:Not all properties displayed):

PS C:\> $Result

Name          Category
----          --------
c_first_item  cat_red
c_second_item cat_blue
c_third_item  cat_red

Union-Object cmdlet 会将所有缺少的属性(带有$Null 值)添加到相关对象:

PS C:\> $Result = $Result | Union-Object
PS C:\> $Result

Name          Category Picture
----          -------- -------
c_first_item  cat_red
c_second_item cat_blue
c_third_item  cat_red
                       cat_blue

【讨论】:

  • 感谢您的解释(以及帮助中心的链接),并对糟糕的问题线程感到抱歉。我会用更清晰的信息更新它,并在完成后通知您。另外,我可能在某人的帮助下找到了答案。我得先试试。 :)
  • 感谢您更新您的问题,我已将其相应地纳入我的回答中
  • 感谢您的更新回答。不幸的是,Union-Object 在此模板中仍然无法正常工作,ConvertFrom-String 永远不会返回 Picture 属性。 Slack 上的某个人帮我想出了一个可行的答案,所以我会给他几天时间自己在这里发布,或者我会自己做,并感谢他的帮助。 :)
  • 认为您的Union-Object 无法解决我的问题,获得更简单的脚本非常有用。但是,我不确定我是否可以按照 SO 标准接受您的答案。如果一个mod可以对此发表评论。 :)
  • 我可能发现了一个极端情况,您 Union-Object 返回一个不应该存在的 Length 属性。哪里可以谈这个?
【解决方案2】:

稍作延迟后,答案如下。 Nicolas Baudin (https://www.linkedin.com/in/nicolas-baudin-63491a111/) 帮助我找到了它。

问题来自模板。由于icon 属性并非在所有集合中都存在,因此该函数难以检索它,实际上它根本没有返回它。诀窍是更改模板以包含一个结构,该结构随后将返回所有属性,包括Picture。此结构由ConvertFrom-String 作为对象返回,其属性是您尝试解析的所有值。

新模板如下所示:

$Template = @'
{Object:*{Name:c_first_item} = \{   
    time = 270

    category = {Category:cat_red}


    random_property = \{
        random_property_value = 10
    \}

    random_property = \{
        random_property_value = 20
    \}
\}}

{Object:*{Name:c_second_item} = \{
    time = 100
    icon = {Picture?:c_third_icon}

    category = {Category:cat_blue}

    random_property = \{
        random_property_value = 10
    \}

    random_property = \{
        random_property_value = 20
    \}
\}}
'@  

命令本身已经适应了新的输出对象,现在是:

$Result = $Data | ConvertFrom-String -TemplateContent $Template |
                  Select-Object -ExpandProperty Object |
                  Union-Object

如您所见,我正在使用您的 Union-Object 函数,因为我有几个模板不会为每个对象输出相同的属性,所以它很方便。这样,我可以使用一个函数来解析我的所有文件。

【讨论】:

    猜你喜欢
    • 2013-03-10
    • 2016-03-12
    • 2016-03-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-17
    相关资源
    最近更新 更多