鉴于此输入...
$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实例...
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
请注意,由于Body 组中使用了greedy quantifier(即(?<Body>.*)),在最后一个属性有尾随空格但没有尾随分号的情况下,该空格将包含在属性值中。如果该行为不受欢迎,您可以将其更改为惰性量词(即(?<Body>.*?))。
我将所有内容解析为有序的哈希表/字典,以便更轻松地将输入文本与输出属性匹配,但您也可以使用常规 Hashtable。
或者,您可以使用 -replace operator 通过在匹配的属性值周围添加引号来将输入文本转换为有效的 PowerShell Hashtable syntax...
# Match the shortest text possible between "Name=" and a ";" or
# a "}" and replace it with that same text surrounded by quotes
$replacementText = $originalText -replace '(?<=[a-z]+=)(?<Value>.*?)(?=;|\s*})', '"${Value}"'
...然后使用Invoke-Expression cmdlet 将其解析为Hashtable 实例...
$properties = Invoke-Expression -Command $replacementText
这个正则表达式假定...
- 所有属性值都需要引用。
- 没有属性值包含
; 或} 字符。
使用和上面一样的输入,下面的代码……
foreach ($pair in $testRecords.GetEnumerator())
{
Write-Host '=================================================='
$originalText = $pair.Value
Write-Host " Original text: $originalText"
# Match the shortest text possible between "Name=" and a ";" or
# a "}" and replace it with that same text surrounded by quotes
$replacementText = $originalText -replace '(?<=[a-z]+=)(?<Value>.*?)(?=;|\s*})', '"${Value}"'
if ([Object]::ReferenceEquals($originalText, $replacementText))
{
Write-Host 'Replacement text is indentical to original text'
}
else
{
Write-Host "Replacement text: $replacementText";
}
$properties = Invoke-Expression -Command $replacementText
Write-Host "Replacement text evaluated 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
}
...产生这个输出...
==================================================
Original text: @{}
Replacement text is indentical to original text
Replacement text evaluated to Hashtable with Count = 0
==================================================
Original text: @{DekId=1}
Replacement text: @{DekId="1"}
Replacement text evaluated to Hashtable with Count = 1
Name Value PrintableValue
---- ----- --------------
DekId 1 1
==================================================
Original text: @{DekId=1+1=2}
Replacement text: @{DekId="1+1=2"}
Replacement text evaluated to Hashtable with Count = 1
Name Value PrintableValue
---- ----- --------------
DekId 1+1=2 1+1=2
==================================================
Original text: @{ }
Replacement text is indentical to original text
Replacement text evaluated to Hashtable with Count = 0
==================================================
Original text: @{ DekId=1 }
Replacement text: @{ DekId="1" }
Replacement text evaluated to Hashtable with Count = 1
Name Value PrintableValue
---- ----- --------------
DekId 1 1
==================================================
Original text: @{ DekId=1+1=2 }
Replacement text: @{ DekId="1+1=2" }
Replacement text evaluated to Hashtable with Count = 1
Name Value PrintableValue
---- ----- --------------
DekId 1+1=2 1+1=2
==================================================
Original text: @{First=A B C;Second=X Y Z}
Replacement text: @{First="A B C";Second="X Y Z"}
Replacement text evaluated to Hashtable with Count = 2
Name Value PrintableValue
---- ----- --------------
Second X Y Z X·Y·Z
First A B C A·B·C
==================================================
Original text: @{First=A B C;Second=X Y Z }
Replacement text: @{First="A B C";Second="X Y Z" }
Replacement text evaluated to Hashtable with Count = 2
Name Value PrintableValue
---- ----- --------------
Second X Y Z X·Y·Z
First A B C A·B·C
==================================================
Original text: @{First=A B C;Second=X Y Z;}
Replacement text: @{First="A B C";Second="X Y Z";}
Replacement text evaluated to Hashtable with Count = 2
Name Value PrintableValue
---- ----- --------------
Second X Y Z X·Y·Z
First A B C A·B·C
==================================================
Original text: @{First=A B C;Second=X Y Z; }
Replacement text: @{First="A B C";Second="X Y Z"; }
Replacement text evaluated to Hashtable with Count = 2
Name Value PrintableValue
---- ----- --------------
Second X Y Z X·Y·Z
First A B C A·B·C
==================================================
Original text: @{First=A B C; Second=X Y Z}
Replacement text: @{First="A B C"; Second="X Y Z"}
Replacement text evaluated to Hashtable with Count = 2
Name Value PrintableValue
---- ----- --------------
Second X Y Z X·Y·Z
First A B C A·B·C
==================================================
Original text: @{First=A B C; Second=X Y Z }
Replacement text: @{First="A B C"; Second="X Y Z" }
Replacement text evaluated to Hashtable with Count = 2
Name Value PrintableValue
---- ----- --------------
Second X Y Z X·Y·Z
First A B C A·B·C
==================================================
Original text: @{First=A B C; Second=X Y Z;}
Replacement text: @{First="A B C"; Second="X Y Z";}
Replacement text evaluated to Hashtable with Count = 2
Name Value PrintableValue
---- ----- --------------
Second X Y Z X·Y·Z
First A B C A·B·C
==================================================
Original text: @{First=A B C; Second=X Y Z; }
Replacement text: @{First="A B C"; Second="X Y Z"; }
Replacement text evaluated to Hashtable with Count = 2
Name Value PrintableValue
---- ----- --------------
Second X Y Z X·Y·Z
First A B C A·B·C
==================================================
Original text: @{First=;Second=X Y Z}
Replacement text: @{First="";Second="X Y Z"}
Replacement text evaluated to Hashtable with Count = 2
Name Value PrintableValue
---- ----- --------------
Second X Y Z X·Y·Z
First <empty>
==================================================
Original text: @{First=;Second=X Y Z }
Replacement text: @{First="";Second="X Y Z" }
Replacement text evaluated to Hashtable with Count = 2
Name Value PrintableValue
---- ----- --------------
Second X Y Z X·Y·Z
First <empty>
==================================================
Original text: @{First=;Second=X Y Z;}
Replacement text: @{First="";Second="X Y Z";}
Replacement text evaluated to Hashtable with Count = 2
Name Value PrintableValue
---- ----- --------------
Second X Y Z X·Y·Z
First <empty>
==================================================
Original text: @{First=;Second=X Y Z; }
Replacement text: @{First="";Second="X Y Z"; }
Replacement text evaluated to Hashtable with Count = 2
Name Value PrintableValue
---- ----- --------------
Second X Y Z X·Y·Z
First <empty>
==================================================
Original text: @{First=; Second=X Y Z}
Replacement text: @{First=""; Second="X Y Z"}
Replacement text evaluated to Hashtable with Count = 2
Name Value PrintableValue
---- ----- --------------
Second X Y Z X·Y·Z
First <empty>
==================================================
Original text: @{First=; Second=X Y Z }
Replacement text: @{First=""; Second="X Y Z" }
Replacement text evaluated to Hashtable with Count = 2
Name Value PrintableValue
---- ----- --------------
Second X Y Z X·Y·Z
First <empty>
==================================================
Original text: @{First=; Second=X Y Z;}
Replacement text: @{First=""; Second="X Y Z";}
Replacement text evaluated to Hashtable with Count = 2
Name Value PrintableValue
---- ----- --------------
Second X Y Z X·Y·Z
First <empty>
==================================================
Original text: @{First=; Second=X Y Z; }
Replacement text: @{First=""; Second="X Y Z"; }
Replacement text evaluated to Hashtable with Count = 2
Name Value PrintableValue
---- ----- --------------
Second X Y Z X·Y·Z
First <empty>
==================================================
Original text: @{First=A B C;Second=}
Replacement text: @{First="A B C";Second=""}
Replacement text evaluated to Hashtable with Count = 2
Name Value PrintableValue
---- ----- --------------
Second <empty>
First A B C A·B·C
==================================================
Original text: @{First=A B C;Second= }
Replacement text: @{First="A B C";Second="" }
Replacement text evaluated to Hashtable with Count = 2
Name Value PrintableValue
---- ----- --------------
Second <empty>
First A B C A·B·C
==================================================
Original text: @{First=A B C;Second=;}
Replacement text: @{First="A B C";Second="";}
Replacement text evaluated to Hashtable with Count = 2
Name Value PrintableValue
---- ----- --------------
Second <empty>
First A B C A·B·C
==================================================
Original text: @{First=A B C;Second=; }
Replacement text: @{First="A B C";Second=""; }
Replacement text evaluated to Hashtable with Count = 2
Name Value PrintableValue
---- ----- --------------
Second <empty>
First A B C A·B·C
==================================================
Original text: @{First=A B C; Second=}
Replacement text: @{First="A B C"; Second=""}
Replacement text evaluated to Hashtable with Count = 2
Name Value PrintableValue
---- ----- --------------
Second <empty>
First A B C A·B·C
==================================================
Original text: @{First=A B C; Second= }
Replacement text: @{First="A B C"; Second="" }
Replacement text evaluated to Hashtable with Count = 2
Name Value PrintableValue
---- ----- --------------
Second <empty>
First A B C A·B·C
==================================================
Original text: @{First=A B C; Second=;}
Replacement text: @{First="A B C"; Second="";}
Replacement text evaluated to Hashtable with Count = 2
Name Value PrintableValue
---- ----- --------------
Second <empty>
First A B C A·B·C
==================================================
Original text: @{First=A B C; Second=; }
Replacement text: @{First="A B C"; Second=""; }
Replacement text evaluated to Hashtable with Count = 2
Name Value PrintableValue
---- ----- --------------
Second <empty>
First A B C A·B·C
==================================================
Original text: @{DekId=; FieldId=1234; OriginalValue=; NewValue=1234}
Replacement text: @{DekId=""; FieldId="1234"; OriginalValue=""; NewValue="1234"}
Replacement text evaluated to Hashtable with Count = 4
Name Value PrintableValue
---- ----- --------------
NewValue 1234 1234
OriginalValue <empty>
DekId <empty>
FieldId 1234 1234
==================================================
Original text: @{DekId=; FieldId=7602; OriginalValue=; NewValue=Alice, Hamburgler}
Replacement text: @{DekId=""; FieldId="7602"; OriginalValue=""; NewValue="Alice, Hamburgler"}
Replacement text evaluated to Hashtable with Count = 4
Name Value PrintableValue
---- ----- --------------
NewValue Alice, Hamburgler Alice,·Hamburgler
OriginalValue <empty>
DekId <empty>
FieldId 7602 7602