我的文本文件中包含以下数据。
author ; testname1
Revision ; 121
Date ; 10/5/2018
Path ; dev/test1
Message ; notes: testdata1
author ; testname2
Revision ; 1212
Date ; 10/6/2018
Path ; dev/test2
Message ; notes: testdata2
author ; testname3
Revision ; 1213
Date ; 10/5/2018
Path ; dev/test3
Message ; notes: testdata3
我想阅读此内容并导出为CSV,如下所示。
author,Revision,Date,Path,Message
testname1,121,10/5/2018,dev/test1,notes: testdata1
testname2,1212,10/6/2018,dev/test2,notes: testdata2
testname3,1213,10/5/2018,dev/test3,notes: testdata3
有什么建议吗?
我尝试了以下代码
$local:InputFilePath = "path of file"
$local:OutFilePathCSV = "path of csv file"
$local:CSVDelimiter = ","
$local:OutDataList = New-Object -TypeName System.Collections.Arraylist
$local:CurrentDataList = New-Object -TypeName System.Collections.Hashtable
Select-String -Path $InputFilePath -Pattern "^[\s]" -NotMatch | ForEach-Object {
$local:CurrentLine = ($_.Line).TrimEnd()
$CurrentLine
$OutDataList.Add($(New-Object -TypeName System.Management.Automation.PSObject -Property $CurrentDataList)) | Out-Null
$CurrentDataList.Clear()
if ($CurrentLine -match "^[\s]*([\w]*)[\s]+(.*)") {
$CurrentDataList.Add($matches[1], $matches[2])
$matches[1]
$matches[2]
#break
}
}
$OutDataList |
Sort-Object -Property Serial |
Select-Object -Property author, Revision, Date, Action, Path |
Export-Csv -Path $OutFilePathCSV -Delimiter $CSVDelimiter -NoTypeInformation
答案 0 :(得分:1)
找到了一种超级简单的方法来解决您的问题,方法是创建哈希表并将其导出到csv:
#requires -Version 3
$path = 'C:\Temp\data.txt'
$data = Get-Content -Path $path -ReadCount 5
$collection = foreach ($obj in $data)
{
$out = [ordered]@{}
foreach ($line in $obj.Split("`n"))
{
$a, $b = ($line -split ';').Trim()
$out[$a] = $b
}
[pscustomobject]$out
}
$newPath = 'C:\Temp\file.csv'
$collection | Export-Csv -Path $newPath -Encoding ascii -NoTypeInformation -Force
此解决方案假定您的文本文档格式正确。
答案 1 :(得分:0)
您在正确的道路上。但是,有两种方法可以做到这一点。这是最简单,最直接的方法。但是,由于您在输入文件中分别列出了所有不同的列,因此,您至少需要至少知道列数和使用的定界符(这里是分号)。< / p>
通过示例文本文件以及尽可能多的代码进行标记,这就是您要执行的操作。
$InputFilePath = "path of file"
$OutFilePathCSV = "path of csv file"
$CSVDelimiter = ","
$OutDataList = New-Object -TypeName System.Collections.Arraylist
$ColumnNumbers = 5
$InputFileDelimter = ';'
$InputFileData = Select-String -Path $InputFilePath -Pattern "^[\s]" -NotMatch
for ($i = 0 ; $i -lt $InputFileData.count; $i += $ColumnNumbers) {
$CurrentLine = New-Object PSObject
for ($j = 0 ; $j -lt $ColumnNumbers; $j++) {
if ($InputFileData[$i+$j].Line -match "^(.*)\s*$InputFileDelimter\s*(.*)\s*$") {
$CurrentLine | Add-Member -MemberType NoteProperty -Name $matches[1] -Value $matches[2]
}
}
$OutDataList.Add($CurrentLine)
}
$OutDataList |
Select-Object -Property Author, Revision, Date, Action, Path |
Export-Csv -Path $OutFilePathCSV -Delimiter $CSVDelimiter -NoTypeInformation
提示/信息:
"^[\s]*([\w]*)[\s]+(.*)"
^[\s]*
是多余的,因为您已经在选择字符串中排除了以空格开头的行。([\w]*)
不会捕获名称中带有空格的列(此处不是必需的,仅供以后参考)。(.*)
也将捕获定界符。"^(.*)\s*$InputFileDelimter\s*(.*)\s*$"
^(.*)\s*
将捕获完整的列名,而定界符前没有空格。如果始终只有一个单词,可以将其交换为^\w*
。$InputFileDelimter\s*(.*)\s*$
将捕获整个列值,而不会在开头或结尾出现空格。注意:
$CSVDelimter
是不必要的,因为Export-CSV
默认使用逗号。Serial
的列,因此排序不会在您的代码中执行任何操作。希望这会有所帮助!使用PowerShell祝您好运!
编辑:
摘自以下另一个答案的评论:Fetch data from txt file and export it to CSV
固定读取计数的另一种方法是使用正则表达式$ data =(Get-Content。\ data.txt -Raw)-split“`n(?= author)”在RegEX的第一个字段处进行拆分。
这实际上是一个非常好的主意,我喜欢它。唯一的问题是,您必须确保始终按属性组将第一列列在第一位。