如何从文本文件导入 PSObject 数组?

问题描述 投票:0回答:3

简单足够了:

PS C:\Users\saunders\Desktop\data>
PS C:\Users\saunders\Desktop\data> ls .\test.csv


    Directory: C:\Users\saunders\Desktop\data


Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
-a----        2023-01-31   1:38 PM            640 test.csv


PS C:\Users\saunders\Desktop\data>
PS C:\Users\saunders\Desktop\data> cat .\test.csv
UserPrincipalName,"DisplayName","Title","UserType","IsLicensed"
[email protected],"Lee Gu","jr engineer","Member","True"
[email protected],"Megan Bowen","recruiter","Member","True"
[email protected],"Grady Archie","sr engineer","Member","True"
[email protected],"Miriam Graham","Director","Member","True"
[email protected],"openmailbox",,"Member","False"
[email protected],"Johanna Lorenz","Senior Engineer","Member","True"
[email protected],"Joni Sherman","recruiter","Member","False"
[email protected],"Alex Wilber","Marketing Assistant","Member","True"
[email protected],"Isaiah Langer","Sales Rep","Member","True"
PS C:\Users\saunders\Desktop\data>
PS C:\Users\saunders\Desktop\data> $test = Import-CSV .\test.csv
PS C:\Users\saunders\Desktop\data>
PS C:\Users\saunders\Desktop\data> $test[3]


UserPrincipalName : [email protected]
DisplayName       : Miriam Graham
Title             : Director
UserType          : Member
IsLicensed        : True



PS C:\Users\saunders\Desktop\data>

但是如何从格式化的text文件中获取CSV格式的数据呢?

PS C:\Users\saunders\Desktop\data>
PS C:\Users\saunders\Desktop\data> $records = Get-Content .\records.txt
PS C:\Users\saunders\Desktop\data>
PS C:\Users\saunders\Desktop\data> $records


UserPrincipalName : [email protected]
DisplayName       : Lee Gu
Title             : jr engineer
UserType          : Member
IsLicensed        : True

UserPrincipalName : [email protected]
DisplayName       : Megan Bowen
Title             : recruiter
UserType          : Member
IsLicensed        : True

UserPrincipalName : [email protected]
DisplayName       : Grady Archie
Title             : sr engineer
UserType          : Member
IsLicensed        : True

UserPrincipalName : [email protected]
DisplayName       : Miriam Graham
Title             : Director
UserType          : Member
IsLicensed        : True

UserPrincipalName : [email protected]
DisplayName       : openmailbox
Title             :
UserType          : Member
IsLicensed        : False

UserPrincipalName : [email protected]
DisplayName       : Johanna Lorenz
Title             : Senior Engineer
UserType          : Member
IsLicensed        : True

UserPrincipalName : [email protected]
DisplayName       : Joni Sherman
Title             : recruiter
UserType          : Member
IsLicensed        : False

UserPrincipalName : [email protected]
DisplayName       : Alex Wilber
Title             : Marketing Assistant
UserType          : Member
IsLicensed        : True

UserPrincipalName : [email protected]
DisplayName       : Isaiah Langer
Title             : Sales Rep
UserType          : Member
IsLicensed        : True

PS C:\Users\saunders\Desktop\data>

这样每条记录的数据都会被转置,然后写入 CSV 文件中的一行。毫无疑问,这个逆运算有一个term。它本身不一定是 CSV,只是上面的示例源自 CSV。

请纠正任何术语错误。


就目前情况而言,$records 对象本身不能直接导出回 CSV:

PS C:\Users\saunders\Desktop\data>
PS C:\Users\saunders\Desktop\data> $records = Get-Content .\records.txt
PS C:\Users\saunders\Desktop\data>
PS C:\Users\saunders\Desktop\data> Export-Csv $records
Export-Csv : Cannot convert 'System.Object[]' to the type 'System.String' required by parameter 'Path'. Specified method is not supported.
At line:1 char:12
+ Export-Csv $records
+            ~~~~~~~~
    + CategoryInfo          : InvalidArgument: (:) [Export-Csv], ParameterBindingException
    + FullyQualifiedErrorId : CannotConvertArgument,Microsoft.PowerShell.Commands.ExportCsvCommand

PS C:\Users\saunders\Desktop\data>

因为它首先必须以某种方式解析。

string powershell csv text-processing psobject
3个回答
3
投票

特别是对于 Windows PowerShell,您可以选择使用

ConvertFrom-String
的基于模板的解析 功能:

# define a template using the data from 2 consecutive records from the input data
$recordTemplate = @'
UserPrincipalName : {UserPrincipalName*:[email protected]}
DisplayName       : {DisplayName:Lee Gu}
Title             : {Title:jr engineer}
UserType          : {UserType:Member}
IsLicensed        : {IsLicensed:True}

UserPrincipalName : {UserPrincipalName*:[email protected]}
'@

# ConvertFrom-String will use the example(s) in the template to infer the format of the remaining records
Get-Content .\records.txt | ConvertFrom-String -TemplateContent $recordTemplate

3
投票

您显示的文本格式是 for-display 格式,由 PowerShell 的

Format-List
cmdlet 生成。

因此,它不适用于 programmatic 处理,因此没有可以解析该格式的标准 cmdlet(请参阅底部部分 re

ConvertFrom-String
)。

对于编程处理,应使用结构化文本格式,例如 JSON 或 CSV,或者 - 为了获得最大的结构灵活性和最佳(尽管有限)类型保真度 - PowerShell 的基于 XML 的 CLIXML 格式,由 生成

Export-Clixml
并被
Import-Clixml
理解。

如果您坚持使用给定的格式,则必须自己进行解析;例如:

# Outputs [pscustomobject] instances that can be exported to CSV, for instance.
((Get-Content -Raw records.txt) -replace ':', '=') -split '\r?\n\r?\n' | 
  ConvertFrom-StringData | 
  ForEach-Object { [pscustomobject] $_ }

上面的内容比较简单,但是:

  • 假设属性values都不包含

    :
    (这可以解决)并且所有值都是单行;此外,这些值受
    \
    字符的解释的影响。作为转义序列的开始(请参阅下一个要点中的 cmdlet 链接)。

  • 有一个不可避免的缺点:因为

    ConvertFrom-StringData
    输出本质上是无序哈希表,所以不会保留属性顺序。

    • 可能会在未来的 PowerShell 版本(7.3.2 之后,截至撰写本文时为当前版本)中解决此问题,这是 GitHub 问题 #19070
    • 的主题

如果维护属性顺序很重要,并且您知道属性名称,则可以通过管道传输到

Select-Object
调用,并将按所需顺序列出的属性名称作为其
-Property
参数。

否则,您必须自己解析文本文件行。


注意:我建议避免过时的、仅限 Windows 的

ConvertFrom-String
cmdlet,尽管它很有诱惑力:

  • 它提供基于分隔符的解析以及基于包含示例值的模板的启发式的解析。

  • 基于分隔符的解析应用了您无法控制的自动类型转换,并且模板语言的文档记录很少,确切的行为很难预测(这在基于启发式的解决方案中是不可避免的)。

  • 也就是说,即使它已从PowerShell(核心)7+删除在Windows上您仍然可以调用它,即通过Windows PowerShell兼容性功能,但是,会产生明显的性能损失


0
投票

虽然尚未完全实现,但类似

wsl >
wsl > pwd
/mnt/c/WINDOWS/system32/awk
wsl >
wsl > awk '{print $1}' input.txt | datamash transpose
A       B       C       D
wsl >
wsl > awk '{print $2}' input.txt | datamash transpose
2014    2013    2014    2014
wsl >
wsl > awk '{print $3}' input.txt | datamash transpose
1002    990     2030    599
wsl >
wsl > cat input.txt
A        2014   1002
B        2013    990
C        2014   2030
D        2014    599
wsl >

矩阵每条记录一次转置一行。

上面的输出,当连接时,将是:

A       B       C       D
2014    2013    2014    2014
1002    990     2030    599

至少乍一看,可以轻松地将其导入为 CSV。然而,这不是 PowerShell 解决方案。

© www.soinside.com 2019 - 2024. All rights reserved.