使用 PowerShell 将字符串解析为对象时遇到问题 [英] Trouble parsing string to object with PowerShell

查看:70
本文介绍了使用 PowerShell 将字符串解析为对象时遇到问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个包含结构化数据的字符串(见下文).我需要把这个字符串转换成一个对象,这样我就可以将它导出到 .csv(或我要求的任何其他文件).我运行了以下代码:

I have a string with structured data (see below). I need to take this string and convert it to an object, so I can export it to .csv (or whatever else is requested of me). I ran the following code:

$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 参数一起使用,但还没有实现.

This is clearly not correct. What is a better way to make this conversion? I thought about using ConvertFrom-String with the TemplateContent parameter, but haven't been able to make that work yet.

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

Here are the first two entries in the string (which contains several users worth of data):

$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
"@

谢谢.

推荐答案

如果:

  • 您可以依赖从不包含 : 自身的值
  • 您不介意生成的自定义对象的属性不反映输入顺序(尽管您可以通过管道传递到 Select-Object 调用枚举轻松但效率低下)属性),
  • you can rely on values never containing : themselves
  • you don't mind that the properties of the resulting custom objects don't reflect the input order (though you could easily, but inefficiently, correct that with piping to a Select-Object call enumerating the properties explicitly),

您可以使用 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 (...)

Note: Casting to [pscustomobject] requires PSv3+; on PSv2, use New-Object PSCustomObject -Property (...)

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

  • $string.Trim() -split '(?m)(?=^City\b)' -ne '' splits the input lines into blocks of lines each representing one object; splitting is performed by lines that start with City; -ne '' filters out the empty block that results from parsing the start of the input.

  • .Trim() 需要忽略字符串开头的空行.
  • .Trim() is needed to ignore empty lines at the start of the string.

$_ -replace ':', '=' |ConvertFrom-StringData 将每个块转换为
= 行,ConvertFrom-StringData 作为一个组转换为一个 [hashtable] 实例;因为哈希表本质上以没有保证的顺序枚举它们的条目,这是属性的输入顺序丢失的地方.

$_ -replace ':', '=' | ConvertFrom-StringData converts each block into
<key>=<value> lines that ConvertFrom-StringData converts as a group to a [hashtable] instance; because hash tables inherently enumerate their entries in no guaranteed order, this is where the input ordering of properties is lost.

Cast [pscustomobject] 将每个hashtable转换成自定义对象,隐式输出;输出可以通过管道传输到 Export-Csv.

Cast [pscustomobject] converts each hashtable to a custom object, which is implicitly output; the output can be piped to Export-Csv.

这篇关于使用 PowerShell 将字符串解析为对象时遇到问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆