【问题标题】:How to make Powershell's Import-Csv correctly import blank spaces如何让 Powershell 的 Import-Csv 正确导入空格
【发布时间】:2021-05-11 01:34:01
【问题描述】:

我有一个 CSV 文件,其中一些单元格中有一个空格,而其他单元格只是空的。如果我跑

" " -eq ""

它返回 False,因此 Powershell 本身可以理解空格和空字符串之间的区别。但是,我有一个包含以下内容的 CSV 文件:

Header0,Header1,Header2,Header3
FillerData, ,,FillerData

当我导入并比较它时,我得到以下信息:

PS C:\> $MyCSV = Import-Csv -Path "C:\MyCSV.csv"
PS C:\> $MyCSV.Header1 -eq " "
False

PS C:\> $MyCSV.Header1 -eq ""
True

PS C:\> $MyCSV.Header2 -eq " "
False

PS C:\> $MyCSV.Header2 -eq ""
True

因此,当它们不相等时,Import-Csv 默认将带有空格的 CSV 条目视为等于空字符串。我真的需要为我的用例导入空格。有什么方法可以让 Import-Csv 正确导入空格而不是将它们视为空字符串?

【问题讨论】:

  • 您能否在此处将 csv 的某些行(包括标题)作为纯文本包含在内?
  • 我添加了一个带有一些填充数据的示例,以显示空格和空字符串之间的区别。
  • 如果您控制 csv 的生成过程,请将有意义的空格用引号括起来 - 例如,请参阅 ConvertTo-Csv 的输出:(new-object pscustomobject -property ([ordered] @{"Header0"="FillerData";"Header1"=" ";"Header2"=$null;"Header3"="FillerData"})) | convertto-csv 给出 "Header0","Header1","Header2","Header3" "FillerData"," ",,"FillerData" - 请注意 " " 为 Header1 的值.
  • 如果您的问题尚未得到完全解答,请考虑 accepting 提供答案或提供反馈。
  • 当然,我认为 >95% 的问题都有可接受的答案。但是,我首先需要验证它是否确实有效。现在,尝试这个我遇到了一个问题,即添加引号会使 Import-Csv 逐字导入它们。

标签: powershell csv


【解决方案1】:

如果我在regex 方面做得更好一点,这可以改进,但这是可行的解决方案,所以基本上Import-Csv 将默认删除空格,除非您指定需要文字空格。一种方法是在每个单元格上添加打开和关闭 ",但由于您的 CSV 没有,添加这些 " 的一种方法是:

$csv = Get-Content ./test.csv

$newCsv = $csv | ForEach-Object {
    $_ -replace '(^|$)','$0"' -replace ',','","'
} | ConvertFrom-Csv

# As you can see, this results in 1 instead of 0
PS /> $newCsv.Header1.Length
1

编辑:

实际上,应该不需要foreach-object。这也很好用:

$newCsv = $csv -replace '(^|$|[\r\n])','$0"' -replace ',','","' | ConvertFrom-Csv

编辑 2:

在下面添加来自他的 cmets 的 mklement0's 示例。

  • 使用ForEach-Object 可降低内存消耗但效率较低:

[^,]+ 匹配除, 之外的任何非空字符序列即任何非空字段。

$newCsv = $csv | ForEach-Object {
    $_ -replace '[^,]+', '"$&"'
} | ConvertFrom-Csv
  • 没有ForEach-Object(最有效的解决方案):
$csv = (Get-Content -Raw ./test.csv) -replace  '[^,\r\n]+', '"$&"' | ConvertFrom-Csv

【讨论】:

  • 啊,所以用引号括起来 CSV 内容可以解决这个问题,很有趣。我将对 CSV 文件和正则表达式进行处理,看看这会将我引向何方。我正在循环中使用 CSV 文件进行大量导入,因此在我在脚本中使用它之前,最好只使用您的示例并将引号写入文件。我会尽快回复你!
  • 好方法;您可以简化为单个 -replace 操作,如下所示:-replace '[^,]+', '"$&"',但请注意 - 与您的方法一样 - 这依赖于没有 embedded , 字符的字段。 (这将要求这些字段已经被双引号,这似乎不是这里的情况)。
  • $& 只是$0 的别名——您可以互换使用它们。 [^,]+ 只匹配除, 之外的任何非空字符,即任何非空字段。如果文件太大而无法放入内存,ForEach-Object 值得直接使用Get-Content 输入。作为一个整体;否则,最有效的解决方案是:(Get-Content -Raw ./test.csv) -replace '[^,\r\n]+', '"$&"' | ConvertFrom-Csv
  • 您提供了正确的解释和方法的基本原理,因此我认为改进您的答案而不是我发布另一个答案是有意义的。随意使用我以前的 cmets 中的信息来更新您的答案。
  • 天哪,当然!谢谢:) 是的,这两种解决方案有效!非常感谢!
猜你喜欢
  • 2021-04-12
  • 2021-09-22
  • 1970-01-01
  • 2021-03-11
  • 2018-01-05
  • 2011-03-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多