读取 1 行制表符分隔数据并导出为“+”分隔时生成的空 CSV 文件
Empty CSV file produced when reading 1 row of tab delimited data and exporting to '+' delimited
(PowerShell) 脚本的 objective 是获取制表符分隔的文本文件,删除 header 行,将分隔符更改为“+”,添加自定义 header 记录并在文件底部添加一个摘要(页脚)行,其中包含数据记录的数量。最后,文件扩展名需要用序号代替。
当原始文件包含超过1行时结果符合要求,但当只有一行(Header加1个数据行)时,输出文件为空。
$dir = "C:\Temp\Data"
$file = "rand1"
$sequencefile = "C:\temp\Sequential\DoNotDeleteSequence.txt"
$sequencenumber = (Get-Content $sequencefile)
$newsequencenumber = ($sequencenumber/1) + 1
Clear-Content $sequencefile
Add-Content $sequencefile $newsequencenumber
$backslash = "\"
$ext = ".txt"
$filename = $dir + $backslash + $file + $ext
$text = "TRAILER = "
$dateText = Get-Date -Format d
$Header1 = "HEADER="
$Header2 = "+PSTG"
$HeaderText = $Header1 + $dateText + $Header2
$tempfile1 = "step1"
$tempfile2 = "step2"
$tempfile3 = "step3"
$tempfile4 = "step4"
$temppstg = "PSTG_NCDLPSTG."
$stepfile1 = $dir + $backslash + $tempfile1 + $ext
$stepfile2 = $dir + $backslash + $tempfile2 + $ext
$stepfile3 = $dir + $backslash + $tempfile3 + $ext
$stepfile4 = $dir + $backslash + $tempfile4 + $ext
$pstgfile = $dir + $backslash + $temppstg + $newsequencenumber
(Get-Content $filename).Replace("+", '') | Set-Content $stepfile1
(Get-Content $stepfile1) | select -Skip 1 | Set-Content $stepfile2
Import-Csv $stepfile2 -Delimiter "`t" | Export-Csv $stepfile3 -Delimiter "+" -NoTypeInformation
Set-Content $stepfile4 $HeaderText
(Get-Content $stepfile3).Replace("""", '') | Add-Content $stepfile4
$records = Import-Csv $stepfile4 | Measure-Object | Select-Object -Expand Count
$textToWrite = $text + $records
Add-Content $stepfile4 $textToWrite
Rename-Item $stepfile4 $pstgfile
我创建了 2 个测试原始文件(制表符分隔)。
C:\Temp\Data\rand1.txt
包含
Header Row
Record1 Data1
C:\Temp\Data\rand2.txt
包含
Header Row
Record1 Data1
Record2 Data2
当rand2.txt
通过代码传递结果是
HEADER=25/03/2019+PSTG
Record1+Data1
Record2+Data2
TRAILER = 2
处理rand1.txt
时,结果为
HEADER=25/03/2019+PSTG
TRAILER = 0
以下两个处理步骤导致了您观察到的行为:
(Get-Content $stepfile1) | select -Skip 1 | Set-Content $stepfile2
Import-Csv $stepfile2 -Delimiter "`t" | Export-Csv $stepfile3 -Delimiter "+" -NoTypeInformation
要了解发生了什么,您只需查看各个处理步骤即可。我正在显示文件 rand1.txt
(左)和 rand2.txt
(右)side-by-side 的输入和输出以说明正在发生的事情。
(Get-Content $stepfile1) | select -Skip 1 | Set-Content $stepfile2
输入:
Header Row Header Row
Record1 Data1 Record1 Data1
Record2 Data2
输出:
Record1 Data1 Record1 Data1
Record2 Data2
此步骤删除 header 行,留下一行 rand1.txt
,但两行 rand2.txt
。这本身并不是您观察到的问题的根本原因,但它为真正的罪魁祸首做好了准备。
Import-Csv $stepfile2 -Delimiter "`t" | Export-Csv $stepfile3 -Delimiter "+" -NoTypeInformation
输入:
Record1 Data1 Record1 Data1
Record2 Data2
输出:
Record1+Data1
Record2+Data2
由于 Import-Csv
和 Export-Csv
的工作方式,rand1.txt
没有输出,但是 rand2.txt
的两个记录都没有输出。
Import-Csv
将分隔文件的行转换为自定义 objects,并将每行的字段转换为这些 objects 的属性,并为这些属性取名从输入文件的第一行开始。
Export-Csv
与它的同级 cmdlet 完全相反:它将自定义 object 列表转换为数据行,并将 object 属性的值转换为字段的数据行。列表中第一个 object 的属性名称决定导出哪些属性,并形成输出文件的 header 行。
由于 rand1.txt
只有一行(即只有 header 行),没有在导入时创建 object,因为没有数据,因此没有数据导出回文件。另一方面,rand2.txt
有两行,所以在导入时你会得到一个 object 具有以下结构(在 JSON 表示法中):
{
"Record1": "Record2",
"Data1": "Data2"
}
然后转换回 header 行 Record1+Data1
和数据行 Record2+Data2
。
后续步骤只会向您创建的中间文本文件添加新的 header 行。如果您在使用 Import-Csv
之前没有删除 header,或者一开始就没有使用 *-Csv
cmdlet,就不会发生此问题。
话虽如此,您的整个处理方式太复杂了。您只需使用以下几行即可获得所需的结果(为简洁起见省略了一些变量定义):
$filename = Join-Path $dir "${file}${ext}"
$records = (Get-Content $filename).Replace('+', '').Replace("`t", '+') |
Select-Object -Skip 1
$newsequencenumber = [int](Get-Content $sequencefile) + 1
$pstgfile = Join-Path $dir "PSTG_NCDLPSTG.${newsequencenumber}"
"HEADER=$(Get-Date -Format d)+PSTG" | Set-Content $ptsgfile
$records | Add-Content $ptsgfile
"TRAILER = $($records.Count)" | Add-Content $ptsgfile
(PowerShell) 脚本的 objective 是获取制表符分隔的文本文件,删除 header 行,将分隔符更改为“+”,添加自定义 header 记录并在文件底部添加一个摘要(页脚)行,其中包含数据记录的数量。最后,文件扩展名需要用序号代替。
当原始文件包含超过1行时结果符合要求,但当只有一行(Header加1个数据行)时,输出文件为空。
$dir = "C:\Temp\Data"
$file = "rand1"
$sequencefile = "C:\temp\Sequential\DoNotDeleteSequence.txt"
$sequencenumber = (Get-Content $sequencefile)
$newsequencenumber = ($sequencenumber/1) + 1
Clear-Content $sequencefile
Add-Content $sequencefile $newsequencenumber
$backslash = "\"
$ext = ".txt"
$filename = $dir + $backslash + $file + $ext
$text = "TRAILER = "
$dateText = Get-Date -Format d
$Header1 = "HEADER="
$Header2 = "+PSTG"
$HeaderText = $Header1 + $dateText + $Header2
$tempfile1 = "step1"
$tempfile2 = "step2"
$tempfile3 = "step3"
$tempfile4 = "step4"
$temppstg = "PSTG_NCDLPSTG."
$stepfile1 = $dir + $backslash + $tempfile1 + $ext
$stepfile2 = $dir + $backslash + $tempfile2 + $ext
$stepfile3 = $dir + $backslash + $tempfile3 + $ext
$stepfile4 = $dir + $backslash + $tempfile4 + $ext
$pstgfile = $dir + $backslash + $temppstg + $newsequencenumber
(Get-Content $filename).Replace("+", '') | Set-Content $stepfile1
(Get-Content $stepfile1) | select -Skip 1 | Set-Content $stepfile2
Import-Csv $stepfile2 -Delimiter "`t" | Export-Csv $stepfile3 -Delimiter "+" -NoTypeInformation
Set-Content $stepfile4 $HeaderText
(Get-Content $stepfile3).Replace("""", '') | Add-Content $stepfile4
$records = Import-Csv $stepfile4 | Measure-Object | Select-Object -Expand Count
$textToWrite = $text + $records
Add-Content $stepfile4 $textToWrite
Rename-Item $stepfile4 $pstgfile
我创建了 2 个测试原始文件(制表符分隔)。
C:\Temp\Data\rand1.txt
包含
Header Row Record1 Data1
C:\Temp\Data\rand2.txt
包含
Header Row Record1 Data1 Record2 Data2
当rand2.txt
通过代码传递结果是
HEADER=25/03/2019+PSTG Record1+Data1 Record2+Data2 TRAILER = 2
处理rand1.txt
时,结果为
HEADER=25/03/2019+PSTG TRAILER = 0
以下两个处理步骤导致了您观察到的行为:
(Get-Content $stepfile1) | select -Skip 1 | Set-Content $stepfile2
Import-Csv $stepfile2 -Delimiter "`t" | Export-Csv $stepfile3 -Delimiter "+" -NoTypeInformation
要了解发生了什么,您只需查看各个处理步骤即可。我正在显示文件 rand1.txt
(左)和 rand2.txt
(右)side-by-side 的输入和输出以说明正在发生的事情。
(Get-Content $stepfile1) | select -Skip 1 | Set-Content $stepfile2
输入:
Header Row Header Row Record1 Data1 Record1 Data1 Record2 Data2
输出:
Record1 Data1 Record1 Data1 Record2 Data2
此步骤删除 header 行,留下一行
rand1.txt
,但两行rand2.txt
。这本身并不是您观察到的问题的根本原因,但它为真正的罪魁祸首做好了准备。Import-Csv $stepfile2 -Delimiter "`t" | Export-Csv $stepfile3 -Delimiter "+" -NoTypeInformation
输入:
Record1 Data1 Record1 Data1 Record2 Data2
输出:
Record1+Data1 Record2+Data2
由于
Import-Csv
和Export-Csv
的工作方式,rand1.txt
没有输出,但是rand2.txt
的两个记录都没有输出。Import-Csv
将分隔文件的行转换为自定义 objects,并将每行的字段转换为这些 objects 的属性,并为这些属性取名从输入文件的第一行开始。Export-Csv
与它的同级 cmdlet 完全相反:它将自定义 object 列表转换为数据行,并将 object 属性的值转换为字段的数据行。列表中第一个 object 的属性名称决定导出哪些属性,并形成输出文件的 header 行。由于
rand1.txt
只有一行(即只有 header 行),没有在导入时创建 object,因为没有数据,因此没有数据导出回文件。另一方面,rand2.txt
有两行,所以在导入时你会得到一个 object 具有以下结构(在 JSON 表示法中):{ "Record1": "Record2", "Data1": "Data2" }
然后转换回 header 行
Record1+Data1
和数据行Record2+Data2
。
后续步骤只会向您创建的中间文本文件添加新的 header 行。如果您在使用 Import-Csv
之前没有删除 header,或者一开始就没有使用 *-Csv
cmdlet,就不会发生此问题。
话虽如此,您的整个处理方式太复杂了。您只需使用以下几行即可获得所需的结果(为简洁起见省略了一些变量定义):
$filename = Join-Path $dir "${file}${ext}"
$records = (Get-Content $filename).Replace('+', '').Replace("`t", '+') |
Select-Object -Skip 1
$newsequencenumber = [int](Get-Content $sequencefile) + 1
$pstgfile = Join-Path $dir "PSTG_NCDLPSTG.${newsequencenumber}"
"HEADER=$(Get-Date -Format d)+PSTG" | Set-Content $ptsgfile
$records | Add-Content $ptsgfile
"TRAILER = $($records.Count)" | Add-Content $ptsgfile