使用PowerShell将字符串解析为对象时遇到问题

时间:2018-07-30 20:57:04

标签: string powershell parsing

我有一个包含结构化数据的字符串(请参见下文)。我需要使用此字符串并将其转换为对象,以便可以将其导出到.csv(或其他要求我执行的操作)。我运行了以下代码:

$data = $string -replace "\s*:\s*","="

但是我的输出看起来像这样:

City=Country=Department=DisplayName=John Doe
DistinguishedName=CN=John Doe, CN=Users, DC=domain, DC=com
EmailAddress=jdoe@domain.com
Enabled=False
Fax=GivenName=John
MobilePhone=Name=John Doe
ObjectClass=user
ObjectGUID=cdb9a45c-80f4-4919-bf43-5db8d9ca83da
Office=OfficePhone=PostalCode=SamAccountName=jdoe
SID=S-1-5-21-2025429266-2000478354-1606980848-16934
State=StreetAddress=Surname=Doe
Title=UserPrincipalName=jdoe@domain.com

这显然是不正确的。什么是进行此转换的更好方法?我曾考虑过将ConvertFrom-String与TemplateContent参数一起使用,但还无法使之工作。

这是字符串中的前两个条目(其中包含多个用户的数据):

$string = @"
City              :
Country           :
Department        :
DisplayName       : John Doe
DistinguishedName : CN=John Doe,CN=Users,DC=domain,DC=com
EmailAddress      : jdoe@domain.com
Enabled           : False
Fax               :
GivenName         : John
MobilePhone       :
Name              : John Doe
ObjectClass       : user
ObjectGUID        : cdb9a45c-80f4-4919-bf43-5db8d9ca83da
Office            :
OfficePhone       :
PostalCode        :
SamAccountName    : jdoe
SID               : S-1-5-21-2025429266-2000478354-1606980848-16934
State             :
StreetAddress     :
Surname           : Doe
Title             :
UserPrincipalName : jdoe@domain.com

City              :
Country           :
Department        :
DisplayName       : DiscoverySearchMailbox{D919BA15-46A6-415f-80AD-7E09334BB852}
DistinguishedName : CN=DiscoverySearchMailbox {D919BA15-46A6-415f-80AD-7E09334BB852},CN=Users,DC=domain,DC=com
EmailAddress      : DiscoverySearchMailbox{D919BA15-46A6-415f-80AD-7E09334BB852}@domain.com
Enabled           : False
Fax               :
GivenName         :
MobilePhone       :
Name              : DiscoverySearchMailbox{D919BA15-46A6-415f-80AD-7E09334BB852}
ObjectClass       : user
ObjectGUID        : 0f35137a-de93-472f-9114-5488a462d178
Office            :
OfficePhone       :
PostalCode        :
SamAccountName    : SM_2187102a90634829b
SID               : S-1-5-21-2438891277-1009865731-3229889747-3109
State             :
StreetAddress     :
Surname           : MsExchDiscoveryMailbox D919BA15-46A6-415f-80AD-7E09334BB852
Title             :
UserPrincipalName : DiscoverySearchMailbox{D919BA15-46A6-415f-80AD-7E09334BB852}@domain.com
"@

谢谢。

3 个答案:

答案 0 :(得分:2)

如果:

  • 您可以依靠自己不包含:的值
  • 您不介意所生成的自定义对象的属性不会反映输入顺序(尽管您可以轻松地但效率低下地通过管道传递到Select-Object调用来显式枚举属性),

您可以使用ConvertFrom-StringData(我建议避免使用挑剔且文献记录不充分的ConvertFrom-String

$string.Trim() -split '(?m)(?=^City\b)' -ne '' | ForEach-Object { 
  [pscustomobject] ($_ -replace ':', '=' | ConvertFrom-StringData)
}  # | Export-Csv ....

注意:投射到[pscustomobject]需要PSv3 +;在PSv2上,使用New-Object PSCustomObject -Property (...)

  • $string.Trim() -split '(?m)(?=^City\b)' -ne ''将输入行分成行块,每行代表一个对象;拆分由以City开头的行执行; -ne ''滤除解析输入开始时产生的空白块。

    • .Trim()需要忽略字符串开头的空行。
  • $_ -replace ':', '=' | ConvertFrom-StringData将每个块转换为
    <key>=<value>行中ConvertFrom-StringData行转换为[hashtable]实例的[pscustomobject]行;因为哈希表固有地以没有保证的顺序枚举其条目,所以这就是属性的输入顺序丢失的地方。

  • Cast Export-Csv将每个哈希表转换为隐式输出的自定义对象;输出可以通过管道传递到match goal with | [ e : expr, H : (is_v_of_expr e = true) |- _ ] => idtac end. (* The reference e was not found in the current environment *)

答案 1 :(得分:0)

转义序列\s所有空格匹配,包括换行符。因此,没有值的行实际上与下一行合并。在换行符处分割字符串,进行替换,然后将字符串数组合并回单个字符串。

$data = $string -split '\r?\n' -replace '\s*:\s*','=' | Out-String

或确保您不替换换行符:

$data = $string -replace '[\t ]*:[\t ]*', '='

编辑:

由于输入数据似乎由多个记录组成,而不仅仅是一个记录,因此您需要按记录对结果字符串进行拆分,以便每个数据集具有单独的字符串。使用ConvertFrom-StringData将每个数据集转换为哈希表,然后将这些哈希表转换为自定义对象。

$data = $string -split '(?<=\r?\n)\r?\n' | ForEach-Object {
    $prop = $_.Trim() -split '\r?\n' -replace '\s*:\s*','=' |
            Out-String |
            ConvertFrom-StringData
    New-Object -Type PSObject -Property $prop
}

在PowerShell v3和更高版本中,您可以使用[PSCustomObject]类型的加速器来代替New-Object

$data = $string -split '(?<=\r?\n)\r?\n' | ForEach-Object {
    $prop = $_.Trim() -split '\r?\n' -replace '\s*:\s*','=' |
            Out-String |
            ConvertFrom-StringData
    [PSCustomObject]$prop
}

然后可以将结果对象列表导出为CSV。

答案 2 :(得分:0)

您在这里:)

Gucci

结果对象看起来像这样

    $a=@"
City              :
Country           :
Department        :
DisplayName       : John Doe
DistinguishedName : CN=John Doe,CN=Users,DC=domain,DC=com
EmailAddress      : jdoe@domain.com
Enabled           : False
Fax               :
GivenName         : John
MobilePhone       :
Name              : John Doe
ObjectClass       : user
ObjectGUID        : cdb9a45c-80f4-4919-bf43-5db8d9ca83da
Office            :
OfficePhone       :
PostalCode        :
SamAccountName    : jdoe
SID               : S-1-5-21-2025429266-2000478354-1606980848-16934
State             :
StreetAddress     :
Surname           : Doe
Title             :
UserPrincipalName : jdoe@domain.com
"@
$b=ConvertFrom-Csv -InputObject $a -Delimiter ':' -Header "key","value"
$c=New-Object -TypeName System.Management.Automation.PSObject 
$b|%{ $c|Add-Member -NotePropertyName $_.key -NotePropertyValue "$($_.value)"}

如果这种解决方案似乎是一个好主意,我将继续研究我的答案。
显然,它需要去除空格和一些更好的变量名,但是我相信您可以自己完成:)