我具有以下格式的String
,需要帮助将其转换为可以轻松访问内部键值对的数据结构。
@{7068="@{DekId=; FieldId=1234; OriginalValue=; NewValue=1234}";7602="@{DekId=; FieldId=7602; OriginalValue=; NewValue=Alice, Hamburgler}";...}
我曾尝试使用ConvertFrom-String
,但是我无法正确操纵String
来满足这种格式。
给出此输入...
$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-Expression
和Hashtable
可以出现在一个值中,或者根据属性/类型需要不同的默认值,则需要更复杂的东西。