如何从 Powershell 中的类似哈希表的文本中提取值?
How can I extract the values from this Hashtable-like text in Powershell?
我有一个以下格式的 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个实例...
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>.*)
),在最后一个 属性 尾随 [=64] 的情况下=] 但没有尾随分号表明 space 将包含在 属性 值中。如果该行为是不可取的,您可以将其更改为惰性量词(即 (?<Body>.*?)
)。
我将所有内容解析为有序 hashtables/dictionaries 只是为了更容易将输入文本与输出属性匹配,但您也可以使用常规 Hashtable
。
或者,您可以通过在匹配的 属性 值周围添加引号来使用 -replace
operator to turn your input text into valid 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
我有一个以下格式的 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个实例...
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>.*)
),在最后一个 属性 尾随 [=64] 的情况下=] 但没有尾随分号表明 space 将包含在 属性 值中。如果该行为是不可取的,您可以将其更改为惰性量词(即 (?<Body>.*?)
)。
我将所有内容解析为有序 hashtables/dictionaries 只是为了更容易将输入文本与输出属性匹配,但您也可以使用常规 Hashtable
。
或者,您可以通过在匹配的 属性 值周围添加引号来使用 -replace
operator to turn your input text into valid 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