【问题标题】:How to remove all quotations mark in the csv file using powershell script?如何使用powershell脚本删除csv文件中的所有引号?
【发布时间】:2020-06-25 23:13:23
【问题描述】:

我想删除导出的 csv 文件中的所有引号字符,当我生成新的 csv 文件时非常烦人,我需要手动删除字符串中包含的所有引号。谁能给我一个Powershell脚本来解决这个问题?谢谢。

$File = "c:\programfiles\programx\file.csv"
(Get-Content $File) | Foreach-Object {
    $_ -replace """, ""
} | Set-Content $File

【问题讨论】:

  • [1] 你试过什么? [grin] ///// [2] 我会尝试 Get-Content 将文件加载为字符串数组,然后 -Replace 替换所有引号。请注意,如果内容需要引号来分隔字段内容,或者如果字段包含引号,这可能会影响您的 CSV 文件。
  • 请把代码添加到您的问题中,以便所有人都能看到......并且在使用代码格式时可以轻松阅读。 [咧嘴]
  • 您知道引号属于有效且符合标准的 csv 格式,不是吗?为什么要删除它们?所有能够读取有效且符合标准的 csv 数据的工具都不应该有引号问题。
  • @Ted.Xiong 问题不是他们有必要——问题是他们会打扰吗?如果不是 - 为什么要努力删除它们。 ;-)
  • 请允许我给你一个标准的建议给新手:如果一个答案解决了你的问题,请accept it点击它旁边的大复选标记(✓),也可以选择投票(投票至少需要 15 个声望点)。如果您发现其他答案有帮助,请给他们投票。接受(您将获得 2 个声望点)和投票可以帮助未来的读者。如果您的问题尚未得到完全解答,请提供反馈或self-answer

标签: powershell csv quotation-marks


【解决方案1】:

使用Export-CSV 导出CSV 文件后,您可以使用Get-Content 将CSV 文件加载到字符串数组中,然后使用Set-Contentreplace 删除引号:

Set-Content -Path sample.csv -Value ((Get-Content -Path sample.csv) -replace '"')

正如mklement0 有用地指出的那样,如果某些行需要引用,这可能会损坏 CSV。该解决方案只是遍历整个文件并将每个引用替换为''

您还可以通过将-Raw 开关与Get-Content 一起使用来加快此过程,这将返回保留换行符的整个字符串,而不是换行符分隔的字符串数组:

Set-Content -NoNewline -Path sample.csv -Value ((Get-Content -Raw -Path sample.csv) -replace '"')

【讨论】:

    【解决方案2】:

    我们中的许多人似乎已经解释过,CSV 文件中有时需要引号。在以下情况下会出现这种情况:

    • 值包含双引号
    • 值包含分隔符
    • 值包含换行符或在字符串的开头或结尾有空格

    在 PS 版本 7 中,您可以选择使用参数 -UseQuotes AsNeeded。 对于旧版本,我制作了这个辅助函数,以便在需要时仅使用引号将其转换为 CSV:

    function ConvertTo-CsvNoQuotes {
        # returns a csv delimited string array with values unquoted unless needed
        [OutputType('System.Object[]')]
        [CmdletBinding(DefaultParameterSetName = 'ByDelimiter')]
        param (
            [Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, Position = 0)]
            [PSObject]$InputObject,
    
            [Parameter(Position = 1, ParameterSetName = 'ByDelimiter')]
            [char]$Delimiter = ',',
    
            [Parameter(ParameterSetName = 'ByCulture')]
            [switch]$UseCulture,
            [switch]$NoHeaders,
            [switch]$IncludeTypeInformation  # by default, this function does NOT include type information
        )
        begin {
            if ($UseCulture) { $Delimiter = (Get-Culture).TextInfo.ListSeparator }
            # regex to test if a string contains a double quote, the delimiter character,
            # newlines or has whitespace at the beginning or the end of the string.
            # if that is the case, the value needs to be quoted.
            $needQuotes = '^\s|["{0}\r\n]|\s$' -f [regex]::Escape($Delimiter)
            # a boolean to check if we have output the headers or not from the object(s)
            # and another to check if we have output type information or not
            $doneHeaders = $doneTypeInfo = $false
        }
    
        process {
            foreach($item in $InputObject) {
                if (!$doneTypeInfo -and $IncludeTypeInformation) {
                    '#TYPE {0}' -f $item.GetType().FullName
                    $doneTypeInfo = $true
                }
                if (!$doneHeaders -and !$NoHeaders) {
                    $row = $item.PsObject.Properties | ForEach-Object {
                        # if needed, wrap the value in quotes and double any quotes inside
                        if ($_.Name -match $needQuotes) { '"{0}"' -f ($_.Name -replace '"', '""') } else { $_.Name }
                    }
                    $row -join $Delimiter
                    $doneHeaders = $true
                }
                $item | ForEach-Object {
                    $row = $_.PsObject.Properties | ForEach-Object {
                        # if needed, wrap the value in quotes and double any quotes inside
                        if ($_.Value -match $needQuotes) { '"{0}"' -f ($_.Value -replace '"', '""') } else { $_.Value }
                    }
                    $row -join $Delimiter
                }
            }
        }
    }
    

    使用您的示例删除现有 CSV 文件中不必要的引号:

    $File = "c:\programfiles\programx\file.csv"
    (Import-Csv $File) | ConvertTo-CsvNoQuotes | Set-Content $File
    

    【讨论】:

      【解决方案3】:

      额外的双引号可用于转义字符串中的双引号:

      $File = "c:\programfiles\programx\file.csv" 
      (Get-Content $File) | Foreach-Object { $_ -replace """", "" } | Set-Content $File
      

      【讨论】:

        【解决方案4】:

        不要将双引号删除到引用的字符串中的一种解决方案:

        $delimiter=","
        $InputFile="c:\programfiles\programx\file.csv"
        $OutputFile="c:\programfiles\programx\resultfile.csv"
        
        #import file in variable (not necessary if your faile is big repeat this import where i use $ContentFile)
        $ContentFile=import-csv $InputFile -Delimiter $delimiter -Encoding utf8 
        
        #list of property of csv file
        $properties=($ContentFile | select -First 1 | Get-Member -MemberType NoteProperty).Name
        
        
        #write header into new file
        $properties -join $delimiter | Out-File $OutputFile -Encoding utf8
        
        #write data into new file
        $ContentFile | %{
        $RowObject=$_                                        #==> get row object
        $Line=@()                                            #==> create array
        $properties | %{$Line+=$RowObject."$_"}              #==> Loop on every property, take value (without quote) inot row object
        $Line -join $delimiter                               #==> join array for get line with delimer and send to standard outut 
        } | Out-File $OutputFile -Encoding utf8 -Append      #==> export result to output file
        

        【讨论】:

          【解决方案5】:

          下次您制作时,powershell 7 中的 export-csv 有一个您可能喜欢的新选项:

          export-csv -UseQuotes AsNeeded
          

          【讨论】:

          • 太棒了。感谢您提醒我,在新版本的 Powershell 中可能会有大量新功能需要探索,这让我的生活变得更加轻松。谢谢。
          【解决方案6】:

          您为什么要在文本编辑器中手动读取 Csv 文件?

          您出于某种原因将它们导出为该格式。要阅读它们,只需将它们重新导入并在屏幕上查看它们,或者重新读取它们并将读数发送到记事本进行阅读。

          Export-Csv -Path D:\temp\book1.csv
          Import-Csv -Path D:\temp\book1.csv | 
          Clip | 
          Notepad # then press crtl+v, then save the notepad file with a new name.
          

          如果您不想要 Csv,则不要导出为 Csv,只需输出为平面文件,而是使用 Out-File。

          更新

          自从您对我的最后评论表明您的最终用例以来。 CSV 转换成 SQL 是很常见的事情。 A quick web search will show you how even provide you with a script. 您还应该查看 PowerShell DBATools 模块。

          How to import data from .csv in SQL Server using PowerShell?

          Importing CSV files into a Microsoft SQL DB using PowerShell

          ImportingCSVsIntoSQLv1.zip

          Four Easy Ways to Import CSV Files to SQL Server with PowerShell

          Find-Module -Name '*dba*' 
          <#
          Version  Name         Repository Description
          -------  ----         ---------- -----------
          1.0.101  dbatools     PSGallery  The community module that enables SQL Server Pros to automate database development and server administration
          ...
          #>
          

          更新

          你的意思是……

          Get-Content 'D:\temp\book1.csv'
          <#
          # Results
          
          "Site","Dept"
          "Main","aaa,bbb,ccc"
          "Branch1","ddd,eee,fff"
          "Branch2","ggg,hhh,iii"
          #>
          
          Get-ChildItem -Path  'D:\temp' -Filter 'book1.csv' | 
          ForEach {
              $NewFile = New-Item -Path 'D:\Temp' -Name "$($PSItem.BaseName).txt"
              Get-Content -Path $PSItem.FullName |
              ForEach-Object {
                  Add-Content -Path $NewFile -Value ($PSItem -replace '"') -WhatIf
              }
          }
          
          <#
          What if: Performing the operation "Add Content" on target "Path: D:\Temp\book1.txt".
          What if: Performing the operation "Add Content" on target "Path: D:\Temp\book1.txt".
          What if: Performing the operation "Add Content" on target "Path: D:\Temp\book1.txt".
          What if: Performing the operation "Add Content" on target "Path: D:\Temp\book1.txt"
          #>
          
          Get-ChildItem -Path  'D:\temp' -Filter 'book1.csv' | 
          ForEach {
              $NewFile = New-Item -Path 'D:\Temp' -Name "$($PSItem.BaseName).txt"
              Get-Content -Path $PSItem.FullName |
              ForEach-Object {
                  Add-Content -Path $NewFile -Value ($PSItem -replace '"')
              }
          }
          
          Get-Content 'D:\temp\book1.txt'
          <#
          # Results
          
          Site,Dept
          Main,aaa,bbb,ccc
          Branch1,ddd,eee,fff
          Branch2,ggg,hhh,iii
          #>
          

          当然,您需要为 csv 文件使用通配符并使用 -Resurse 获取所有目录和错误处理程序以确保您没有文件名冲突。

          【讨论】:

          • 我需要导出为 csv,因为我需要分隔符选项并将其存储在数据库中
          • 但是 SQL 或其他 DB 按预期读取 CSV 文件。读进去就不会带引号了,就像你在Excel中打开csv一样,它会自动删除引号。如果您说,您试图将整个文件作为 blob 与单个记录行/列插入,我可以看到,但您没有这么说。 --- sqlshack.com/importing-and-working-with-csv-files-in-sql-server
          • 其实我需要把csv文件转换成txt文件,然后把这些数据FTP到后端数据库来加载数据。
          【解决方案7】:

          请记住,如果您在数据中嵌入了双引号,这可能会破坏您的数据,这是这个想法的另一个变体...... [grin]

          它的作用......

          • 定义输入和输出完整文件名
          • 从临时目录中抓取*.tmp 文件
          • 过滤前三个文件和三个基本属性
          • 创建要使用的文件
          • 加载文件内容
          • 用空替换双引号
          • 将清理后的文件保存到第二个文件名
          • 显示文件的原始版本和清理后的版本

          代码...

          $TestCSV = "$env:TEMP\Ted.Xiong_-_Test.csv"
          $CleanedTestCSV = $TestCSV -replace 'Test', 'CleanedTest'
          
          Get-ChildItem -LiteralPath $env:TEMP -Filter '*.tmp' -File |
              Select-Object -Property Name, LastWriteTime, Length -First 3 |
              Export-Csv -LiteralPath $TestCSV -NoTypeInformation
          
          (Get-Content -LiteralPath $TestCSV) -replace '"', '' |
              Set-Content -LiteralPath $CleanedTestCSV
          
          Get-Content -LiteralPath $TestCSV
          '=' * 30
          Get-Content -LiteralPath $CleanedTestCSV
          

          输出...

          "Name","LastWriteTime","Length"
          "hd4130E.tmp","2020-03-13 5:23:06 PM","0"
          "hd418D4.tmp","2020-03-12 11:47:59 PM","0"
          "hd41F7D.tmp","2020-03-13 5:23:09 PM","0"
          ==============================
          Name,LastWriteTime,Length
          hd4130E.tmp,2020-03-13 5:23:06 PM,0
          hd418D4.tmp,2020-03-12 11:47:59 PM,0
          hd41F7D.tmp,2020-03-13 5:23:09 PM,0
          

          【讨论】:

            【解决方案8】:

            如上所述,引号对 csv 有效,但要删除它们,您需要将替换操作中的引号作为特殊字符进行转义:

            $File = "c:\programfiles\programx\file.csv"
            (Get-Content $File) | Foreach-Object {
                $_ -replace "`"", ""
            } | Set-Content $File
            

            【讨论】:

            • 如何设置脚本来读取同一路径中不同文件名的所有文件?
            • 我和其他人提供的所有选项都允许您这样做。您必须进行文件递归以获得多个文件名,使用 Get-ChildItem -Recurse,运行清理代码块,然后保存。
            • @postanote 我可以只包含所有 csv 文件吗?你能告诉我怎么做吗?
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2015-07-26
            • 2017-04-21
            • 1970-01-01
            • 1970-01-01
            • 2021-07-07
            • 1970-01-01
            相关资源
            最近更新 更多