0

我有所有用户文件夹的文件夹信息。它被转储到一个 CSV 文件中,如下所示:

Servername, F:\Users\user, 9,355.7602 MB, 264, 3054, 03/15/2000 13:28:48, 12/10/2018 11:58:29

由于第三列中的千位分隔符,我们无法按原样处理数据。我可以再次运行报告脚本,但我们有很多文件服务器,特别是其中一台上有大量用户,因此再次运行它非常耗时。逗号存在的原因是数据被写为字符串而不是数字。

我可以导入和转换,唯一的问题是任何超过 1000 的数字都会出错,然后所有其他数据都是 1 列。我想替换两个数字之间的任何逗号。使用 PowerShell 似乎并不难,但我没有任何运气找到任何东西。

4

2 回答 2

3

如果您假设数据列是逗号加空格分隔的,并且您的数字没有空格,则可以使用-replace运算符。

$line = 'Servername, F:\Users\user, 9,355.7602 MB, 264, 3054, 03/15/2000 13:28:48, 12/10/2018 11:58:29'
$line -replace '(?<=\d),(?=\d)'

如果您正在从文件中读取数据,您可以使用Get-Content读取数据,替换您的数据,然后使用Set-Content更新文件。

(Get-Content file.csv) -replace '(?<=\d),(?=\d)' | Set-Content file.csv

如果文件很大,您可以使用更快的switch语句。

$data = switch -regex -file file.csv {
          '(?<=\d),(?=\d)' { $_ -replace '(?<=\d),(?=\d)' }
          default {$_}
        }
$data | Set-Content file.csv

解释:

  • (?<=\d)(?<=)使用匹配单个数字的肯定后向断言\d
  • (?=\d)(?=)使用与单个数字匹配的肯定前瞻断言。您可以将其替换为(?=\d{3})以匹配逗号后的 3 个连续数字。
  • 由于您想用空字符串替换目标逗号,因此不需要替换字符串。

通常,最好坚持使用处理 CSV 数据或文件的命令。但是,如果您的数据包含逗号并且您没有限定文本,则可能难以区分数据和分隔符。如果您有明确的区分方法,最好使用ConvertFrom-Csv处理已读取的数据或Import-Csv处理文件。您将需要在文件或命令中定义标题。

于 2019-11-18T21:53:19.617 回答
0

编辑

我的疏忽是,数据集中的 没有分隔,这导致此答案无法按预期工作,因为在解析 CSV 时逗号被视为列分隔符。如果列数据是转义属性,我将保留它,因为它确实解释了如何按照您的预期一般操作数据。但是,下面的@AdminOfThings 答案应该适用于您的特定情况,并且将修复错误定义的列,而不依赖于首先将 CSV 内容解析为 CSV。


使用 导入数据Import-Csv,然后删除,第三列中的任何数据。这假设您没有值,,小数点分隔符在哪里:

如果您在 CSV 中有标头,则无需定义标头名称或花哨地将 CSV 写回:

Import-Csv -Path \path\to\file.csv | Foreach-Object {
  $_.ColumnName = $_.ColumnName -replace ','
} | Export-Csv -NoTypeInformation -Path \path\to\file.csv

其工作方式是我们将 CSV 作为可操作的 CSV 导入PSCustomObject,然后对于每一行,我们采用具有大小的列名并,从中删除。最后,我们将修改PSCustomObject后的内容导出回原始 CSV。

如果您没有标题,它会变得有点棘手,因为我们必须定义临时标题,但Export-Csv没有选项可以跳过写出标题:

Import-Csv -Path \path\to\file.csv -Headers Col1, Col2, Col3, Col4, Col5, Col6, Col7 |
  Foreach-Object {
    $_.Col3 = $_.Col3 -replace ','
  } | ConvertTo-Csv | Select-Object -Skip 1 |
  Set-Content -Path \path\to\file.csv

这与第一个代码块的作用相同,但由于我们不想导出临时标头,因此我们必须发挥创造力。首先,请注意我们使用临时标题名称引用目标列。不是将修改后的 CSV 对象直接传送Export-CsvConvertTo-Csv. 然后我们使用Select-Object跳过转换后的 CSV 文本的第一行,即标题,因此我们只有行数据和列值。最后,我们使用Set-Content将不带标题的 CSV 文本写回原始文件。

于 2019-11-18T21:58:11.117 回答