如何在PowerShell中筛选列中的空值

huangapple go评论100阅读模式
英文:

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-CsvConvertFrom-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-CsvImport-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-CsvImport-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 &#39;&#39;) 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 = @&#39;     # Or as in your revised question:
1,2,3,4       # &quot;1&quot;,&quot;2&quot;,&quot;3&quot;,&quot;4&quot;
3,5,6,        # &quot;3&quot;,&quot;5&quot;,&quot;6&quot;,&quot;&quot;
A,B,C,        # &quot;A&quot;,&quot;B&quot;,&quot;C&quot;,&quot;&quot;
D,F,G,H       # &quot;D&quot;,&quot;F&quot;,&quot;G&quot;,&quot;H&quot;
&#39;@
# Import-Csv -Path &quot;test.csv&quot; -Header &quot;P&quot;,&quot;A&quot;,&quot;E&quot;,&quot;S&quot; |
#     Where-Object { $_.S } |Export-Csv &quot;export.csv&quot; -Force -NoTypeInformation
$Csv |ConvertFrom-Csv -Header &quot;P&quot;,&quot;A&quot;,&quot;E&quot;,&quot;S&quot; |
    Where-Object { $_.S } |ConvertTo-Csv

&quot;P&quot;,&quot;A&quot;,&quot;E&quot;,&quot;S&quot;
&quot;1&quot;,&quot;2&quot;,&quot;3&quot;,&quot;4&quot;
&quot;D&quot;,&quot;F&quot;,&quot;G&quot;,&quot;H&quot;

> 1) if you check for $Null; $Null should be at the left side of the comparison operator

huangapple
  • 本文由 发表于 2023年3月7日 16:52:36
  • 转载请务必保留本文链接:https://go.coder-hub.com/75659764.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定