从txt文件中获取数据并将其导出为CSV

时间:2018-10-17 13:28:29

标签: powershell

我的文本文件中包含以下数据。

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

2 个答案:

答案 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的第一个字段处进行拆分。

这实际上是一个非常好的主意,我喜欢它。唯一的问题是,您必须确保始终按属性组将第一列列在第一位。