PowerShell脚本将双引号内的逗号替换为零

PowerShell脚本将双引号内的逗号替换为零,powershell,csv,Powershell,Csv,我有一个逗号分隔的CSV文件,我打算将双引号中的逗号替换为零,并将双引号替换为零: 编者按:此问题的原始形式要求“将[分隔符]更改为管道”(|),这不再是要求;gms0ulman的答案是在它还没有写完的时候写的 任何帮助都将不胜感激 在: 输出: 我将把它分解为两个步骤。另一个StackOverflow用户可能会给您一行 Import-Csv C:\test.csv | Export-Csv tempfile.csv -Delimiter "|" (Get-Content tempfile.cs

我有一个逗号分隔的CSV文件,我打算将双引号中的逗号替换为零,并将双引号替换为零:

编者按:此问题的原始形式要求“将[分隔符]更改为管道”(
|
),这不再是要求;gms0ulman的答案是在它还没有写完的时候写的

任何帮助都将不胜感激

在:

输出:


我将把它分解为两个步骤。另一个StackOverflow用户可能会给您一行

Import-Csv C:\test.csv | Export-Csv tempfile.csv -Delimiter "|"
(Get-Content tempfile.csv).Replace(",","").Replace('"',"") | Out-File test1.csv

以下内容应满足您的要求(在PSv5.1中测试):

  • Import Csv
    将您的Csv文件读取到自定义对象(
    [pscustomobject]
    实例)中,这些对象的属性包含已删除双引号的列值

    • 由于列值随后存储在不同的属性中,因此可以盲目地替换列内部
      实例,而不必担心列分隔
      实例
    • 封闭的双引号被自动剥离是一个有益的副作用,尽管必须注意不要在输出读取时重新引入它们
  • 问题是在修改对象后不能使用
    导出Csv
    ,因为它总是在所有输出值周围添加双引号(返回)

  • 因此,必须使用
    ForEach对象
    ,为每个自定义对象执行自定义迷你脚本:

    • -Begin{$writeHeader=$True}
      在开始时执行一次,表示需要在第一个数据行之前输出头行

    • $\u.psobject.properties
      是输入对象上定义的所有属性的集合,以标题列命名,并包含给定数据行的值

    • $\pObject.properties.Name-join',
      输出标题行,只需将属性名称(列标题)与
      连接,以生成单个输出字符串

    • $.psobject.properties.Value-replace',“
      删除任何内部值
      实例(将其替换为空字符串)和
      -join',”
      再次按原样连接结果值,输出数据行

  • 设置内容
    -这比此处的
    输出文件
    更可取,因为输出对象已经是字符串-用于写入输出文件

    • 注意
      -Encoding
      参数以控制输出字符编码-根据需要进行调整

    • 在Windows PowerShell(v5.1之前的版本)中,不使用
      -Encoding
      将默认为系统的“ANSI”代码页(即使帮助主题声称使用ASCII),而
      Out File
      将默认为UTF-16LE(“Unicode”)


    • 您的csv是否有标题?要更改的值是否在同一列中

      如果它看起来像这样:

      h1,h2,h3
      1,2,"Test,ABC"
      3,4,"Test,DEF"
      
      这应该起作用:

      $Csv = Import-Csv -path C:\MyFile.csv
      $Csv.H3 | foreach {$_.Replace('"',"").Replace(",","")}
      
      编辑: 成功了。但基本上与mklement0的解决方案相同

      $Csv = Import-Csv -path C:\MyFile.csv
      $Csv | Foreach {$_.H3 = $_.H3.Replace(",","")}
      $CsvObject = $Csv | Convertto-Csv -NoTypeInformation
      $CsvObject.replace('"','') | 
      Set-Content C:\OutFile.Csv
      

      导入CSV。将其转换为具有不同分隔符的CSV。替换逗号。将分隔符转换回。替换双引号。写出结果文件

      Import-Csv -Path C:\MyFile.csv |
          ConvertTo-Csv -Delimiter '|' | 
          ForEach-Object { $_ -replace ',',[String]::Empty } | 
          ConvertFrom-Csv -Delimiter '|' | 
          ConvertTo-Csv |
          ForEach-Object { $_ -replace -replace '"',[String]::Empty } |
          Set-Content -Path C:\MyFile_fixed.csv
      

      @我认为这是必需的,但OP已经在代码中完成了这一部分。原始问题指定分隔符从
      更改为
      |
      。。。我把它放在那里,因为我认为最好一次完成,而不是像OP那样遍历文件;无论最终目的是什么,++都是一种聪明的方法(由于读写文件两次,速度会很慢,但这是否重要取决于用例)。除非您担心PSv2的兼容性,否则您可以使用
      Get Content-Raw
      ;相反,如果文件太大,无法立即放入内存,请在
      ForEach
      调用中执行
      .Replace
      调用。更好的是,如果使用
      converttocsv-NotypeInformation
      ,就可以避免使用中间文件,如Bacon Bits的答案所示;也许您这样做只是为了可读性,但请注意,使用在内存中收集所有结果的中间变量对于大型文件是有问题的。您可以只使用单个管道,一次处理一个对象。狡辩:
      $CsvObject
      是一个不幸的变量名,因为它包含一个字符串(行)数组。很好。我解决这个问题的方法是在创建csv文件之前尝试解决格式问题,但这可能会受到数据源的限制。有时似乎过度依赖txt文件、csv文件等。这可能是cmd的后遗症。有趣的是,导入Csv会生成一个对象,但Convertto Csv会生成字符串,乍一看似乎是违反直觉的。请允许我向新手提供标准建议:如果答案解决了您的问题,请单击大复选标记接受它(✓) 在它旁边,也可以选择向上投票(向上投票需要至少15个信誉点)。如果你发现其他答案有帮助,请向上投票。接受(你将获得2个信誉点)和向上投票有助于未来的读者。请参阅。
      h1,h2,h3
      1,2,"Test,ABC"
      3,4,"Test,DEF"
      
      $Csv = Import-Csv -path C:\MyFile.csv
      $Csv.H3 | foreach {$_.Replace('"',"").Replace(",","")}
      
      $Csv = Import-Csv -path C:\MyFile.csv
      $Csv | Foreach {$_.H3 = $_.H3.Replace(",","")}
      $CsvObject = $Csv | Convertto-Csv -NoTypeInformation
      $CsvObject.replace('"','') | 
      Set-Content C:\OutFile.Csv
      
      Import-Csv -Path C:\MyFile.csv |
          ConvertTo-Csv -Delimiter '|' | 
          ForEach-Object { $_ -replace ',',[String]::Empty } | 
          ConvertFrom-Csv -Delimiter '|' | 
          ConvertTo-Csv |
          ForEach-Object { $_ -replace -replace '"',[String]::Empty } |
          Set-Content -Path C:\MyFile_fixed.csv