英文:
how to filter empty values in a column in powershell
问题
我有输入文件 text.csv
"#P","#A","#E","#S"
"1","2","3","4"
"3","5","6",""
"A","B","C",""
"D","F","G","H"
我想要输出 CSV 文件 export.csv 如下
"P","A","E","S"
"1","2","3","4"
"D","F","G","H"
$File1 = Import-Csv -Path "test.csv" -Header "P","A","E","S" | Where { $_.S -ne $null } | Export-Csv "export.csv" -Force -NoTypeInformation
英文:
i have input file text.csv
"#P","A","E","S"
"1","2","3","4"
"3","5","6",""
"A","B","C",""
"D","F","G","H"
I want output csv file export.csv as
"P","A","E","S"
"1","2","3","4"
"D","F","G","H"
$File1 = Import-Csv -Path "test.csv" -Header "P","A","E","S" | Where { $_.S -ne $null } | Export-Csv "export.csv" -Force -NoTypeInformation
答案1
得分: 0
以下是翻译好的部分:
如前面的评论中所解释的,“逗号分隔值 (CSV)”文件通常以纯文本形式存储表格数据(数字和文本),在这种情况下,每一行将具有相同数量的字段。
基于这一点,您可能会假设Import-Csv
和ConvertFrom-Csv
永远不会返回$Null
作为属性(列)值,而只是返回空字符串:
$Csv = @'
1,2,3,4
3,5,6,
A,B,C,
D,F,G,H
'@
$Csv | ConvertFrom-Csv -Header "P","A","E","S" |
ForEach-Object { if ($Null -eq $_.S) { 'Null' } else { 'String' } }
String
String
String
String
但要小心这个假设,因为情况并不总是如此。如果不仅省略了最后一个值,而且还省略了前面的逗号,有关的ConvertFrom-Csv
和Import-Csv
命令可能会返回$Null
(请注意,以下示例中的A,B,C
后面没有逗号):
$Csv = @'
1,2,3,4
3,5,6,
A,B,C
D,F,G,H
'@
$Csv | ConvertFrom-Csv -Header "P","A","E","S" |
ForEach-Object { if ($Null -eq $_.S) { 'Null' } else { 'String' } }
String
String
Null
String
此外,有一个与有关的ConvertFrom-Csv
和Import-Csv
命令中的问题有关的不幸错误,即由ConvertFrom-Csv读取的空列的最后一个单元格不一致为$Null
(#17702):
$Csv = @'
1,2,3,
3,5,6,
A,B,C,
D,F,G,
'@
$Csv | ConvertFrom-Csv -Header "P","A","E","S" |
ForEach-Object { if ($Null -eq $_.S) { 'Null' } else { 'String' } }
String
String
String
Null
因此,最好是谨慎处理,同时测试$Null
($Null -ne $_.S
)以及空字符串($_.S -ne ''
),这可以简化为:... | Where-Object { $_.S } |...
,这将在所涉及的字段不为空(或$Null
)时产生所谓的“真”条件,参见Bool 转换:
$Csv = @' # 或按照您修改后的问题中的方式:
1,2,3,4 # "1","2","3","4"
3,5,6, # "3","5","6",""
A,B,C, # "A","B","C",""
D,F,G,H # "D","F","G","H"
'@
$Csv | ConvertFrom-Csv -Header "P","A","E","S" |
Where-Object { $_.S } | ConvertTo-Csv
"P","A","E","S"
"1","2","3","4"
"D","F","G","H"
英文:
As explained earlier in the comments, a Comma-separated values (csv) file typically stores tabular data (numbers and text) in plain text, in which case each line will have the same number of fields.
Based on this you might assume that the Import-Csv
and ConvertFrom-Csv
should never return a $Null
for a property (column) value but just an empty string:
$Csv = @'
1,2,3,4
3,5,6,
A,B,C,
D,F,G,H
'@
$Csv |ConvertFrom-Csv -Header "P","A","E","S" |
ForEach-Object { if ($Null -eq $_.S) { 'Null' } else { 'String' } }
String
String
String
String
But be careful with this assumption as this is not always the case. If not just the last value is omitted but also the preceding comma, the concerned ConvertFrom-Csv
- and Import-Csv
cmdlet might return a $Null
(note that there is no comma behind the A,B,C
in the following example):
$Csv = @'
1,2,3,4
3,5,6,
A,B,C
D,F,G,H
'@
$Csv |ConvertFrom-Csv -Header "P","A","E","S" |
ForEach-Object { if ($Null -eq $_.S) { 'Null' } else { 'String' } }
String
String
Null
String
Besides that, there is an unfortunate bug in the concerned ConvertFrom-Csv
- and Import-Csv
cmdlet where the last cell of an empty column read by ConvertFrom-Csv is inconsistently $Null
#17702
:
$Csv = @'
1,2,3,
3,5,6,
A,B,C,
D,F,G,
'@
$Csv |ConvertFrom-Csv -Header "P","A","E","S" |
ForEach-Object { if ($Null -eq $_.S) { 'Null' } else { 'String' } }
String
String
String
Null
Therefore I would be better safe than sorry and test on both $Null
($Null -ne $_.S
)<Sup>1)</Sup> and an empty string ($_.S -ne ''
) which can be simplified to just: ... |Where-Object { $_.S } |...
this results in a so called "Truthy" condition if the concerned field is not empty (or $Null
), see also Conversion to Bool):
$Csv = @' # Or as in your revised question:
1,2,3,4 # "1","2","3","4"
3,5,6, # "3","5","6",""
A,B,C, # "A","B","C",""
D,F,G,H # "D","F","G","H"
'@
# Import-Csv -Path "test.csv" -Header "P","A","E","S" |
# Where-Object { $_.S } |Export-Csv "export.csv" -Force -NoTypeInformation
$Csv |ConvertFrom-Csv -Header "P","A","E","S" |
Where-Object { $_.S } |ConvertTo-Csv
"P","A","E","S"
"1","2","3","4"
"D","F","G","H"
> 1) if you check for $Null
; $Null
should be at the left side of the comparison operator
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论