这简单足够了:
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>
因为它首先必须以某种方式解析。
特别是对于 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
您显示的文本格式是 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
输出本质上是无序哈希表,所以不会保留属性顺序。
如果维护属性顺序很重要,并且您知道属性名称,则可以通过管道传输到
Select-Object
调用,并将按所需顺序列出的属性名称作为其 -Property
参数。
否则,您必须自己解析文本文件行。
ConvertFrom-String
cmdlet,尽管它很有诱惑力:
它提供基于分隔符的解析以及基于包含示例值的模板的启发式的解析。
基于分隔符的解析应用了您无法控制的自动类型转换,并且模板语言的文档记录很少,确切的行为很难预测(这在基于启发式的解决方案中是不可避免的)。
也就是说,即使它已从PowerShell(核心)7+中删除,在Windows上您仍然可以调用它,即通过Windows PowerShell兼容性功能,但是,会产生明显的性能损失。
虽然尚未完全实现,但类似
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 解决方案。