从xml节点中的文本中提取数值

时间:2015-03-19 19:58:59

标签: xml string powershell

我目前有一个类似于此的日志文件:

<AutoRun>
    <Info>Log file enabled: C:\Sync.xml</Info>
    <Info>Exit attribute has been enabled.</Info>
    <Info>Launching command: Run</Info>
    <Run>
        <Info></Info>
        <Info></Info>
    </Run>
    <Infolog>
                 get    Number of failures: 0
                 Number of Warnings: 0
                 Have resolvable Warnings: False
                 Number of Operations: 5
                 Number of Conflicts: 0

                 Get C:\ with ChangeType: None and Status: Replacing.
                 Get C:\ with ChangeType: None and Status: Replacing.
                 Get C:\ with ChangeType: None and Status: Replacing.
    </Infolog>
</AutoRun>

我试图解析文本并执行以下操作:

  1. 干净地获取文字行

    示例:失败次数:0,警告次数:0

  2. 获取以下值后的值:

  3. 我通过这样做得到了文本:

    [xml]$Log = get-content "C:\Synchronize.xml"
    $results = $Log.AutoRun.Infolog
    

    并且认为我可以通过这样做来检索这条线:

    Select-String -InputObject $a -Pattern 'Number of failures:'
    

    但这会返回infolog节点中的所有内容,而不仅仅是我之后的行。我正在努力理解如何完成这两项任务。

    这是我在阅读前两条建议后得出的结论。:

    string[]]$Log = get-content "C:\Synchronize.xml" 
    $results = $Log | Select-String -Pattern 'Number of failures:\s+(\d+)' | %{$_.Matches.Groups.Value[1]}
    

2 个答案:

答案 0 :(得分:1)

Select-String为InputObject参数获取String[]。但是,XML元素是一个带有嵌入换行符的单个字符串。您传入的是单个字符串并在其中搜索而不是单独的行。

如果要将此字符串与Select-String一起使用,则需要先将其拆分为行。您可以使用String.Split方法执行此操作。您还可以将String.Trim应用于结果以修剪空白以获得更清晰的文本行。

$results = $Log.AutoRun.Infolog.Split("`n") | % { $_.Trim() }
$results | Select-String -Pattern 'Number of failures:'

请注意,当传入InputObject时,PowerShell的行为与用作参数的行为不同,因此您需要管道string[]以搜索每个字符串。

来自https://technet.microsoft.com/en-us/library/hh849903.aspx

  

使用InputObject参数与管道字符串不同   选择字符串。差异如下:

     

- 当您将多个字符串(&#34;集合&#34;)传递给Select-String时,Select-String会搜索每个字符串中的指定文本   string并返回包含搜索文本的每个字符串。

     

- 使用InputObject参数提交字符串集合时,Select-String将集合视为单个组合   string,如果找到搜索文本,则将字符串作为一个单元返回   在任何字符串中。

答案 1 :(得分:0)

还有更多内容,但问题的根源是带有InfoLog文本的文本被读作一个单独的字符串。如果你看这个,你会得到更符合你期望的结果。我不认为这是最好的解决方案,但它突出了问题

$Log.AutoRun.Infolog -split "[`r`n]" | Select-String -Pattern 'Number of failures'

Select-String将返回包含匹配项的字符串。因此,在您的示例中,它将返回您请求的匹配项。 David's answer更详细地说明了这一点的原因,这里再说一遍是多余的。

认为您至少需要PowerShell 3.0,但是您可以隔离数字并从Select-String返回的匹配对象中提取它。

$Log.AutoRun.Infolog | Select-String -Pattern 'Number of failures:\s+(\d+)' | %{$_.Matches.Groups.Value[1]}

Select-String默认返回Microsoft.PowerShell.Commands.MatchInfo而不是基本字符串。它们具有关于定义的匹配的各种属性。如果未指定任何属性,则默认返回整个匹配项。但是,我想深入研究属性,我想提取正则表达式(\d+)中定义的捕获组。如果从右到左删除属性,您可以更好地了解其中的内容。

  • $_.Matches.Groups.Value
  • $_.Matches.Groups
  • $_.Matches

%ForEach-Object的别名,我忘记删除。可以返回多个匹配项。我们将结果视为一个数组并检查每个数组。

假设该行总是有数字,它将只返回“:”之后的数字。如果它有返回单词的更改,您可以使用\S+代替\d+