如何在Powershell中从类似Hashtable的文本中提取值?

问题描述 投票:-1回答:1

我具有以下格式的String,需要帮助将其转换为可以轻松访问内部键值对的数据结构。

@{7068="@{DekId=; FieldId=1234; OriginalValue=; NewValue=1234}";7602="@{DekId=; FieldId=7602; OriginalValue=; NewValue=Alice, Hamburgler}";...}

我曾尝试使用ConvertFrom-String,但是我无法正确操纵String来满足这种格式。

powershell parsing hashmap hashtable string-conversion
1个回答
2
投票

给出此输入...

$testRecords = [Ordered] @{
       0  = "@{}";                           # No values
       1  = "@{DekId=1}";                    # Single value
       2  = "@{DekId=1+1=2}"                 # Single value with equal sign
      10  = "@{ }";                          # No values (with padding)
      11  = "@{ DekId=1 }";                  # Single value (with padding)
      12  = "@{ DekId=1+1=2 }"               # Single value with equal sign (with padding)
                                              # +------------------+--------------------+----------------+
                                              # | Separating space | Trailing semicolon | Trailing space |
                                              # +------------------+--------------------+----------------+
      100 = "@{First=A B C;Second=X Y Z}";    # |        No        |         No         |       No       |
      101 = "@{First=A B C;Second=X Y Z }";   # |        No        |         No         |       Yes      |
      102 = "@{First=A B C;Second=X Y Z;}";   # |        No        |         Yes        |       No       |
      103 = "@{First=A B C;Second=X Y Z; }";  # |        No        |         Yes        |       Yes      |
      104 = "@{First=A B C; Second=X Y Z}";   # |        Yes       |         No         |       No       |
      105 = "@{First=A B C; Second=X Y Z }";  # |        Yes       |         No         |       Yes      |
      106 = "@{First=A B C; Second=X Y Z;}";  # |        Yes       |         Yes        |       No       |
      107 = "@{First=A B C; Second=X Y Z; }"; # |        Yes       |         Yes        |       Yes      |
      # First property empty                  # +------------------+--------------------+----------------+
      200 = "@{First=;Second=X Y Z}";         # |        No        |         No         |       No       |
      201 = "@{First=;Second=X Y Z }";        # |        No        |         No         |       Yes      |
      202 = "@{First=;Second=X Y Z;}";        # |        No        |         Yes        |       No       |
      203 = "@{First=;Second=X Y Z; }";       # |        No        |         Yes        |       Yes      |
      204 = "@{First=; Second=X Y Z}";        # |        Yes       |         No         |       No       |
      205 = "@{First=; Second=X Y Z }";       # |        Yes       |         No         |       Yes      |
      206 = "@{First=; Second=X Y Z;}";       # |        Yes       |         Yes        |       No       |
      207 = "@{First=; Second=X Y Z; }";      # |        Yes       |         Yes        |       Yes      |
      # Second property empty                 # +------------------+--------------------+----------------+
      300 = "@{First=A B C;Second=}";         # |        No        |         No         |       No       |
      301 = "@{First=A B C;Second= }";        # |        No        |         No         |       Yes      |
      302 = "@{First=A B C;Second=;}";        # |        No        |         Yes        |       No       |
      303 = "@{First=A B C;Second=; }";       # |        No        |         Yes        |       Yes      |
      304 = "@{First=A B C; Second=}";        # |        Yes       |         No         |       No       |
      305 = "@{First=A B C; Second= }";       # |        Yes       |         No         |       Yes      |
      306 = "@{First=A B C; Second=;}";       # |        Yes       |         Yes        |       No       |
      307 = "@{First=A B C; Second=; }";      # |        Yes       |         Yes        |       Yes      |
                                              # +------------------+--------------------+----------------+
     7068 = "@{DekId=; FieldId=1234; OriginalValue=; NewValue=1234}";
     7602 = "@{DekId=; FieldId=7602; OriginalValue=; NewValue=Alice, Hamburgler}";
}

...以下使用正则表达式提取周围的@{ },然后进行字符串拆分以将内部内容解析为[Ordered] hashtable实例...

[Ordered]

将产生以下输出...

foreach ($pair in $testRecords.GetEnumerator())
{
    Write-Host '=================================================='

    if ($pair.Value -notmatch '@{\s*(?<Body>.*)\s*}')
    {
        Write-Warning "Pattern failed to match input ""$($pair.Value)""."
    }
    else
    {
        $properties = [Ordered] @{}
        $bodyText = $Matches['Body']

        if (-not [String]::IsNullOrWhiteSpace($bodyText))
        {
            foreach ($propertyText in $bodyText -split ';\s*')
            {
                # In case the property value contains an equal sign, split
                # on only the first =, producing a two-element array
                $propertyName, $propertyValue = $propertyText -split '=', 2
                if (-not [String]::IsNullOrEmpty($propertyName))
                {
                    $properties[$propertyName] = $propertyValue
                }
            }
        }
        Write-Host "Parsed input ""$($pair.Value)"" to $($properties.GetType().Name) with Count = $($properties.Count)"
        $properties.GetEnumerator() `
            | Select-Object -Property `
                'Name', `
                'Value', `
                @{
                    Name = 'PrintableValue';
                    Expression = {
                        return $(
                            if ($_.Value -eq $null) {
                                '<null>'
                            } elseif ($_.Value.Length -eq 0) {
                                '<empty>'
                            } else {
                                $_.Value -replace '\s', [Char] 0x00B7 # Middle dot
                            }
                        )
                    };
                } `
            | Out-Host
    }
}

注意,由于================================================== Parsed input "@{}" to OrderedDictionary with Count = 0 ================================================== Parsed input "@{DekId=1}" to OrderedDictionary with Count = 1 Name Value PrintableValue ---- ----- -------------- DekId 1 1 ================================================== Parsed input "@{DekId=1+1=2}" to OrderedDictionary with Count = 1 Name Value PrintableValue ---- ----- -------------- DekId 1+1=2 1+1=2 ================================================== Parsed input "@{ }" to OrderedDictionary with Count = 0 ================================================== Parsed input "@{ DekId=1 }" to OrderedDictionary with Count = 1 Name Value PrintableValue ---- ----- -------------- DekId 1 1· ================================================== Parsed input "@{ DekId=1+1=2 }" to OrderedDictionary with Count = 1 Name Value PrintableValue ---- ----- -------------- DekId 1+1=2 1+1=2· ================================================== Parsed input "@{First=A B C;Second=X Y Z}" to OrderedDictionary with Count = 2 Name Value PrintableValue ---- ----- -------------- First A B C A·B·C Second X Y Z X·Y·Z ================================================== Parsed input "@{First=A B C;Second=X Y Z }" to OrderedDictionary with Count = 2 Name Value PrintableValue ---- ----- -------------- First A B C A·B·C Second X Y Z X·Y·Z· ================================================== Parsed input "@{First=A B C;Second=X Y Z;}" to OrderedDictionary with Count = 2 Name Value PrintableValue ---- ----- -------------- First A B C A·B·C Second X Y Z X·Y·Z ================================================== Parsed input "@{First=A B C;Second=X Y Z; }" to OrderedDictionary with Count = 2 Name Value PrintableValue ---- ----- -------------- First A B C A·B·C Second X Y Z X·Y·Z ================================================== Parsed input "@{First=A B C; Second=X Y Z}" to OrderedDictionary with Count = 2 Name Value PrintableValue ---- ----- -------------- First A B C A·B·C Second X Y Z X·Y·Z ================================================== Parsed input "@{First=A B C; Second=X Y Z }" to OrderedDictionary with Count = 2 Name Value PrintableValue ---- ----- -------------- First A B C A·B·C Second X Y Z X·Y·Z· ================================================== Parsed input "@{First=A B C; Second=X Y Z;}" to OrderedDictionary with Count = 2 Name Value PrintableValue ---- ----- -------------- First A B C A·B·C Second X Y Z X·Y·Z ================================================== Parsed input "@{First=A B C; Second=X Y Z; }" to OrderedDictionary with Count = 2 Name Value PrintableValue ---- ----- -------------- First A B C A·B·C Second X Y Z X·Y·Z ================================================== Parsed input "@{First=;Second=X Y Z}" to OrderedDictionary with Count = 2 Name Value PrintableValue ---- ----- -------------- First <empty> Second X Y Z X·Y·Z ================================================== Parsed input "@{First=;Second=X Y Z }" to OrderedDictionary with Count = 2 Name Value PrintableValue ---- ----- -------------- First <empty> Second X Y Z X·Y·Z· ================================================== Parsed input "@{First=;Second=X Y Z;}" to OrderedDictionary with Count = 2 Name Value PrintableValue ---- ----- -------------- First <empty> Second X Y Z X·Y·Z ================================================== Parsed input "@{First=;Second=X Y Z; }" to OrderedDictionary with Count = 2 Name Value PrintableValue ---- ----- -------------- First <empty> Second X Y Z X·Y·Z ================================================== Parsed input "@{First=; Second=X Y Z}" to OrderedDictionary with Count = 2 Name Value PrintableValue ---- ----- -------------- First <empty> Second X Y Z X·Y·Z ================================================== Parsed input "@{First=; Second=X Y Z }" to OrderedDictionary with Count = 2 Name Value PrintableValue ---- ----- -------------- First <empty> Second X Y Z X·Y·Z· ================================================== Parsed input "@{First=; Second=X Y Z;}" to OrderedDictionary with Count = 2 Name Value PrintableValue ---- ----- -------------- First <empty> Second X Y Z X·Y·Z ================================================== Parsed input "@{First=; Second=X Y Z; }" to OrderedDictionary with Count = 2 Name Value PrintableValue ---- ----- -------------- First <empty> Second X Y Z X·Y·Z ================================================== Parsed input "@{First=A B C;Second=}" to OrderedDictionary with Count = 2 Name Value PrintableValue ---- ----- -------------- First A B C A·B·C Second <empty> ================================================== Parsed input "@{First=A B C;Second= }" to OrderedDictionary with Count = 2 Name Value PrintableValue ---- ----- -------------- First A B C A·B·C Second · ================================================== Parsed input "@{First=A B C;Second=;}" to OrderedDictionary with Count = 2 Name Value PrintableValue ---- ----- -------------- First A B C A·B·C Second <empty> ================================================== Parsed input "@{First=A B C;Second=; }" to OrderedDictionary with Count = 2 Name Value PrintableValue ---- ----- -------------- First A B C A·B·C Second <empty> ================================================== Parsed input "@{First=A B C; Second=}" to OrderedDictionary with Count = 2 Name Value PrintableValue ---- ----- -------------- First A B C A·B·C Second <empty> ================================================== Parsed input "@{First=A B C; Second= }" to OrderedDictionary with Count = 2 Name Value PrintableValue ---- ----- -------------- First A B C A·B·C Second · ================================================== Parsed input "@{First=A B C; Second=;}" to OrderedDictionary with Count = 2 Name Value PrintableValue ---- ----- -------------- First A B C A·B·C Second <empty> ================================================== Parsed input "@{First=A B C; Second=; }" to OrderedDictionary with Count = 2 Name Value PrintableValue ---- ----- -------------- First A B C A·B·C Second <empty> ================================================== Parsed input "@{DekId=; FieldId=1234; OriginalValue=; NewValue=1234}" to OrderedDictionary with Count = 4 Name Value PrintableValue ---- ----- -------------- DekId <empty> FieldId 1234 1234 OriginalValue <empty> NewValue 1234 1234 ================================================== Parsed input "@{DekId=; FieldId=7602; OriginalValue=; NewValue=Alice, Hamburgler}" to OrderedDictionary with Count = 4 Name Value PrintableValue ---- ----- -------------- DekId <empty> FieldId 7602 7602 OriginalValue <empty> NewValue Alice, Hamburgler Alice,·Hamburgler 组(即greedy quantifier)中使用的Body,在最后一个属性具有尾部空格但没有尾部分号的情况下,该空格将包含在属性值中。如果不希望出现这种情况,则可以将其更改为惰性量词(即(?<Body>.*))。

我将所有内容解析为有序的哈希表/字典,只是为了更轻松地将输入文本与输出属性进行匹配,但是您也可以使用常规的(?<Body>.*?)


这里是一个快速,幼稚的解决方案,它通过插入默认值(我使用了Hashtable,但可以是Hashtable或其他任何东西来处理7068的数据(但没有处理7602,因为您有未用引号的字符串)您想要的)出现在$null ...

0

然后将修改后的文本传递到=;以返回等效的PS> '@{DekId=; FieldId=1234; OriginalValue=; NewValue=1234}' | Tee-Object -Variable 'originalText' @{DekId=; FieldId=1234; OriginalValue=; NewValue=1234} PS> Invoke-Expression -Command $originalText Invoke-Expression : At line:1 char:9 + @{DekId=; FieldId=1234; OriginalValue=; NewValue=1234} + ~ Missing statement after '=' in hash literal. At line:1 char:39 + @{DekId=; FieldId=1234; OriginalValue=; NewValue=1234} + ~ Missing statement after '=' in hash literal. At line:1 char:1 + Invoke-Expression -Command $originalText + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : ParserError: (:) [Invoke-Expression], ParseException + FullyQualifiedErrorId : MissingStatementInHashLiteral,Microsoft.PowerShell.Commands.InvokeExpressionCommand PS> $originalText -replace '=;', '=$null;' | Tee-Object -Variable 'replacedText' @{DekId=$null; FieldId=1234; OriginalValue=$null; NewValue=1234} PS> Invoke-Expression -Command $replacedText | Tee-Object -Variable 'replacedTable' Name Value ---- ----- NewValue 1234 OriginalValue DekId FieldId 1234 PS> $replacedTable | Get-Member TypeName: System.Collections.Hashtable Name MemberType Definition ---- ---------- ---------- Add Method void Add(System.Object key, System.Object value), void IDictionary.Add(System.Object key, System.Object value) [snip] PS> $replacedTable['NewValue'] 1234 PS> $replacedTable['OriginalValue'] PS> ,使您可以直接访问每对。最后一条命令不会产生任何输出,因为检索到的值为Invoke-Expression

当然,如果Invoke-ExpressionHashtable可以出现在一个值中,或者根据属性/类型需要不同的默认值,则需要更复杂的东西。

© www.soinside.com 2019 - 2024. All rights reserved.