解析文本文件并保存为 .csv 文件

3

我有一个文本 (.txt) 文件,看起来像这样:

人员类型    人员姓名       人员编号   状态         主管姓名                 应付工资名称      应用程序   供应商名称   开始日期    结束日期    是否归档
机构        D'Cunha, Yionue 123456   未输入     Power, Mehash           项目        合同承包商                       SUPPLIER_1 10-DEC-16  16-DEC-16   否
员工        Vughila, Proshont132456   工作中     Miro, Profal            公司-abcde月薪支付 INPayroll                10-DEC-16  16-DEC-16   否
                                                                      月薪
员工        Diiri, Maaor   113456   未输入     Kargannkir, Bivnath      公司-abcde月薪支付 INPayroll                10-DEC-16  16-DEC-16   否
                                                                      月薪
员工        Kimit, Gongobhar111111   工作中     Chondorkor, Avissku      公司-abcde项目    INProjects               10-DEC-16  16-DEC-16   否
                                                                      月薪
员工        Kalvornu, Churali110077   工作中     Kindipur, Barinakir      公司-abcde月薪支付 INPayroll                10-DEC-16  16-DEC-16   否
                                                                      月薪
机构        Dhilorii, Bohishik100009   未输入     Nook, Lurukont           项目        合同承包商                       SUPPLIER_2
我是一名有用的助手,可以为您翻译文本。
我从一个软件生成的报告中获得了这个文件。我想解析这个文件并将数据导出到CSV。我尝试了 this,但是它没有帮助,因为我的数据结构非常不同。
然后我尝试了这个:
$input = Get-Content "C:\Users\user.name\Desktop\GBS\text_file.txt"  

$data = $input[1..($input.Length - 1)]

$maxLength = 0

$objects = foreach ($record in $data) {
    $split = $record -split "\s{2,}|\t+"
    if ($split.Length -gt $maxLength) {
        $maxLength = $split.Length
    }
    $props = @{}
    for ($i=0; $i -lt $split.Length; $i++) {
        $props.Add([String]($i+1), $split[$i])
    }
    New-Object -TypeName PSObject -Property $props
}

$headers = [String[]](1..$maxLength)

$objects | 
    Select-Object $headers | 
    Export-Csv -NoTypeInformation -Path "C:\Users\user.name\Desktop\GBS\out.csv"

但是这样会破坏每行的第二行。问题在于,在原始文本文件中,每隔一行也是第一行的一部分。而且在某些情况下,第三行甚至也是数据的第一行的一部分。

如果有任何信息可以提供来更好地表达我的问题,请告诉我。


在 @Ansgar 的评论后,我尝试了这个:

# read text file into single string and remove header
$rawText = Get-Content 'C:\path\to\input.txt' | Out-String

# split string into individual records
$data = $rawText -replace "`r" -split '\n\n+' | Select-Object -Skip 1

$parsedData = foreach ($record in $data) {
    $prop = @{}
    $record -split '\n' | ForEach-Object {
        $prop['PersonType'] += $_.Substring(0, 10).Trim()
        $prop['PersonName'] += $_.Substring(10, 16).Trim()
        $prop['PersonNumber'] += $_.Substring(26, 9).Trim()
        $prop['ApprovalStatus'] += $_.Substring(35, 13).Trim()
        $prop['Supervisor'] += $_.Substring(48, 11).Trim()
        $prop['PayrollName'] += $_.Substring(59, 16).Trim()
        $prop['ApplicationName'] += $_.Substring(75, 13).Trim()
        $prop['Supplier'] += $_.Substring(88, 9).Trim()
        $prop['StartDate'] += $_.Substring(97, 12).Trim()
        $prop['EndDate'] += $_.Substring(109, 9).Trim()
        $prop['Archived'] += $_.Substring(118, 8).Trim()
    }

    New-Object -Type PSObject -Property $prev
}

$parsedData | Export-Csv 'C:\path\to\output.txt' -NoType

但现在我在目标文件夹中得到了一个空的输出CSV文件。我是不是在某个地方漏掉了什么?


如果您能掌握报告所使用的原始数据,那么您会受益匪浅。这样,您就不必撤销报告生成器对数据所做的操作。报告生成器可能试图在报告中节省空间并使其更易读。但是这两个目标都会妨碍您。 - Walter Mitty
嗨沃尔特,谢谢你的及时回复。那是一个主要问题之一。我无法获取报告或以任何方式修改报告。它生成这些报告,并以.txt格式每周向我提供文件的转储。我只是将.txt文件中的一部分数据复制粘贴到这里。 - Rurojnikenshin_183
我刚刚意识到你的个人记录没有用空行分隔,所以我的建议根本行不通。此外,看起来任意字段可以在下一行中具有值或完全为空。你需要做的第一件事是定义标准,通过这些标准你可以编程区分新记录和继续记录,否则这永远不会奏效。 - Ansgar Wiechers
1个回答

0
我有一个解决方案,但是...
它使用了两个分割,第一个将单词(Person|Agency|Employee)
用于拆分记录(存在需要if的缺陷),
第二个在换行符处拆分,并解析偏移量+长度。
由于示例数据不一致,这也并不完美。
$InFile = 'Q:\Test\2016-12\19\41225200.txt'
$OutFile= 'C:\path\to\output.txt'

$Delimiter = '(Person|Agency|Employee)'
#'$Escaped   = [regex]::Escape($Delimiter)
$Split     = "(?!^)(?=$Delimiter)"

$parsedData = (Get-Content $InFile -Raw) -split $Split | 
    ForEach-Object {
        $prop = @{}
        If ($_.Length -ge 30 ) {
            ForEach ($Line in $_.split("`n")) {
                $Line+=" "*130
                $prop['PersonType']      += $Line.Substring( 0, 10).Trim()
                $prop['PersonName']      += $Line.Substring(10, 16).Trim()
                $prop['PersonNumber']    += $Line.Substring(26,  9).Trim()
                $prop['ApprovalStatus']  += $Line.Substring(35, 13).Trim()
                $prop['Supervisor']      += $Line.Substring(48, 11).Trim()
                $prop['PayrollName']     += $Line.Substring(59, 16).Trim()
                $prop['ApplicationName'] += $Line.Substring(75, 12).Trim()
                $prop['Supplier']        += $Line.Substring(87, 10).Trim()
                $prop['StartDate']       += $Line.Substring(97,  9).Trim()
                $prop['EndDate']         += $Line.Substring(108, 9).Trim()
                $prop['Archived']        += $Line.Substring(117, 8).Trim()
            }
        }
        New-Object -TypeName PSObject -Property $prop
}
$parsedData

输出

Supervisor      : ApplicatioName
ApplicationName : t Date End DName
Archived        :
PersonType      : Person   AType
PersonName      : pproval     Supe
Supplier        : ate Archiv
StartDate       : ed
ApprovalStatus  : yroll NameStatus
PayrollName     : n Supplier  Star
PersonNumber    : rvisor PaNumber
EndDate         :


Supervisor      : Power,Mehash
ApplicationName : Projects
Archived        : No
PersonType      : AgencyContractor
PersonName      : D'Cunha, Yionue
Supplier        : CONTRACTSUPPLIER_1
StartDate       : 10-DEC-16
ApprovalStatus  : NOT ENTERED
PayrollName     :
PersonNumber    : 123456
EndDate         : 16-DEC-16


Supervisor      : Miro,Profal
ApplicationName : Payroll
Archived        : NoNo
PersonType      : Employee
PersonName      : Vughila,Proshont
Supplier        :
StartDate       : 10-DEC-1610-DEC-16
ApprovalStatus  : WORKING
PayrollName     : Company-abcde INMonthly
PersonNumber    : 132456
EndDate         : 16-DEC-1616-DEC-16

我的尝试导出为 CSV 也是空的。


谢谢!那真的非常有帮助。虽然我仍在努力,一旦找到答案就会发布。同时,非常感谢您!对于回复迟迟不能,我深表歉意,因为我当时不在城里。 - Rurojnikenshin_183

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接