Powershell 转换为不带引号的Csv输出

Powershell 转换为不带引号的Csv输出,powershell,csv,Powershell,Csv,我正在使用converttocsv获得逗号分隔的输出 get-process | convertto-csv -NoTypeInformation -Delimiter "," 它的输出如下: "__NounName","Name","Handles","VM","WS","..... 但是,我希望得到不带引号的输出,如 __NounName,Name,Handl

我正在使用
converttocsv
获得逗号分隔的输出

get-process | convertto-csv -NoTypeInformation -Delimiter ","
它的输出如下:

"__NounName","Name","Handles","VM","WS",".....
但是,我希望得到不带引号的输出,如

__NounName,Name,Handles,VM,WS....

我没有花太多时间寻找删除引号。但是,这里有一个解决办法

get-process | Export-Csv -NoTypeInformation -Verbose -Path $env:temp\test.csv
$csv = Import-Csv -Path $env:temp\test.csv

这是一个快速的解决方法,可能有更好的方法可以做到这一点。

这里有一种删除引号的方法

get-process | convertto-csv -NoTypeInformation -Delimiter "," | % {$_ -replace '"',''} 

但是,如果其中一个项目包含
,它将被删除!

这与公认的答案非常相似,但它有助于防止不必要地删除“真实”引号

这将执行以下操作:

$objtable | convertto-csv -Delimiter "|" -notypeinformation | select -Skip $headers | % { $_ -replace '"\|"', "|"} | % { $_ -replace '""', '"'} | % { $_ -replace "^`"",''} | % { $_ -replace "`"$",''} | out-file "$OutputPath$filename" -fo -en ascii
  • 删除以行开头的引号
  • 删除行尾的引号
  • 用单独的分隔符替换括起分隔符的引号

因此,如果其中一个值实际上不仅包含引号,而且还包含引号分隔符引号序列,这可能会非常少见。我遇到了这个问题,发现了这个问题,但对答案不满意,因为如果使用c包含一个分隔符,该分隔符应保留引号。消除不必要的双引号是一件好事

下面的解决方案似乎解决了一般情况下以及可能导致问题的所有变体的此问题

我在别处找到了这个答案,并用它为SO社区编写了一个示例答案

归属:regex 100%归Russ Loski所有

在函数中编码,从CSV中删除DoubleQuotes

function Remove-DoubleQuotesFromCsv
{
    param (
        [Parameter(Mandatory=$true)]
        [string]
        $InputFile,

        [string]
        $OutputFile
    )

    if (-not $OutputFile)
    {
        $OutputFile = $InputFile
    }

    $inputCsv = Import-Csv $InputFile

    $quotedData = $inputCsv | ConvertTo-Csv -NoTypeInformation

    $outputCsv = $quotedData | % {$_ -replace  `
        '\G(?<start>^|,)(("(?<output>[^,"]*?)"(?=,|$))|(?<output>".*?(?<!")("")*?"(?=,|$)))' `
        ,'${start}${output}'}

    $outputCsv | Out-File $OutputFile -Encoding utf8 -Force
}

我发现Kory的答案不适用于原始字符串在一行中包含多个空白字段的情况。例如,“ABC”、“0”可以,但“ABC”、“0”处理不正确。它停止在“、”之后替换引号。我通过在第一个参数末尾附近添加“
|(?)
”来修复它,如下所示:

% {$_ -replace  `
    '\G(?<start>^|,)(("(?<output>[^,"]*?)"(?=,|$))|(?<output>".*?(?<!")("")*?"(?=,|$))|(?<output>))', `
    '${start}${output}'}
001,002,003
004,005,006
Import-Csv -Path .\source.csv -Delimiter ',' -Header A,B,C | select A,C | ConvertTo-Csv -NoTypeInformation -Delimiter ',' | % {$_ -replace '"',''} | Out-File -Encoding utf8 .\target.csv
%{$\替换`
“\G(?^ |,)(((?[^,]*?)”(?=,|$))(?*(?)”`
“${start}${output}”

今天我在一张桌子上工作,在我预览记事本中的CSV文件时思考了这个问题,并决定看看其他人想出了什么。似乎很多人都把解决方案复杂化了。
下面是一种从PowerShell中导出CSV cmdlet生成的CSV文件中删除引号的简单方法。

使用以下数据创建一个TEST.csv文件。

“ID”、“名称”、“状态”
“5”、“斯蒂芬妮”、“亚利桑那州”
“4”、“梅勒妮”、“俄勒冈州”
“2”、“凯蒂”、“德克萨斯州”
“8”、“史蒂夫”、“爱达荷州”
“9”、“多莉”、“田纳西”

另存为:TEST.csv

function Remove-DoubleQuotesFromCsv
{
    param (
        [Parameter(Mandatory=$true)]
        [string]
        $InputFile,

        [string]
        $OutputFile
    )

    if (-not $OutputFile)
    {
        $OutputFile = $InputFile
    }

    $inputCsv = Import-Csv $InputFile

    $quotedData = $inputCsv | ConvertTo-Csv -NoTypeInformation

    $outputCsv = $quotedData | % {$_ -replace  `
        '\G(?<start>^|,)(("(?<output>[^,"]*?)"(?=,|$))|(?<output>".*?(?<!")("")*?"(?=,|$)))' `
        ,'${start}${output}'}

    $outputCsv | Out-File $OutputFile -Encoding utf8 -Force
}
将文件内容存储在$Test变量中
$Test=获取内容。\Test.csv

加载$Test变量以查看get-content cmdlet的结果
$Test

再次加载$Test变量并用逗号替换所有(“,”),然后通过删除每个引号来修剪开始和结束

$Test.Replace('","',",").TrimStart('"').TrimEnd('"')
$Test.Replace('","',",").TrimStart('"').TrimEnd('"') | Out-File .\TEST.csv -Force -Confirm:$false
Import-Csv .\TEST.csv
Get-Content .\TEST.csv
$Test = Get-Content .\TEST.csv
$Test.Replace('","',",").TrimStart('"').TrimEnd('"') | Out-File .\TEST.csv -Force -Confirm:$false
保存/替换TEST.csv文件

$Test.Replace('","',",").TrimStart('"').TrimEnd('"')
$Test.Replace('","',",").TrimStart('"').TrimEnd('"') | Out-File .\TEST.csv -Force -Confirm:$false
Import-Csv .\TEST.csv
Get-Content .\TEST.csv
$Test = Get-Content .\TEST.csv
$Test.Replace('","',",").TrimStart('"').TrimEnd('"') | Out-File .\TEST.csv -Force -Confirm:$false
使用导入Csv测试新文件输出并获取内容:

$Test.Replace('","',",").TrimStart('"').TrimEnd('"')
$Test.Replace('","',",").TrimStart('"').TrimEnd('"') | Out-File .\TEST.csv -Force -Confirm:$false
Import-Csv .\TEST.csv
Get-Content .\TEST.csv
$Test = Get-Content .\TEST.csv
$Test.Replace('","',",").TrimStart('"').TrimEnd('"') | Out-File .\TEST.csv -Force -Confirm:$false
总之,这项工作可以用两行代码来完成

$Test.Replace('","',",").TrimStart('"').TrimEnd('"')
$Test.Replace('","',",").TrimStart('"').TrimEnd('"') | Out-File .\TEST.csv -Force -Confirm:$false
Import-Csv .\TEST.csv
Get-Content .\TEST.csv
$Test = Get-Content .\TEST.csv
$Test.Replace('","',",").TrimStart('"').TrimEnd('"') | Out-File .\TEST.csv -Force -Confirm:$false

根据您的CSV数据的病态程度(或“全功能”),其中一个发布的解决方案已经可以工作了

Kory Gill发布的解决方案几乎完美无瑕——剩下的唯一问题是,包含行分隔符的单元格也会删除引号
\r\n
,这导致许多工具出现问题

解决方案是向字符类表达式添加换行符:

$fixedData = $quotedData | % {$_ -replace  `
'\G(?<start>^|,)(("(?<output>[^,"\n]*?)"(?=,|$))|(?<output>".*?(?<!")("")*?"(?=,|$)))' `
,'${start}${output}'}
$fixedData=$quotedData |%{$\替换`

“\G(?^ |,)(((?[^,“\n]*?)”(?=,|$))(?*(?)我写这篇文章是为了我的需要:

function ConvertTo-Delimited {

    [CmdletBinding()]
    param(
        [Parameter(ValueFromPipeline=$true,Mandatory=$true)]
        [psobject[]]$InputObject,
        [string]$Delimiter='|',
        [switch]$ExcludeHeader
    )
    Begin {

        if ( $ExcludeHeader -eq $false ) {
            @(
                $InputObject[0].PsObject.Properties | `
                Select-Object -ExpandProperty Name
            ) -Join $Delimiter          
        }

    }
    Process {

        foreach ($item in $InputObject) {
            @(
                $item.PsObject.Properties | `
                Select-Object Value | `
                ForEach-Object { 
                    if ( $null -ne $_.Value ) {$_.Value.ToString()} 
                    else {''} 
                }
            ) -Join $Delimiter
        }

    }
    End {}

}
用法:

$Data = @(
    [PSCustomObject]@{
        A = $null
        B = Get-Date
        C = $null
    }
    [PSCustomObject]@{
        A = 1
        B = Get-Date
        C = 'Lorem'
    }
    [PSCustomObject]@{
        A = 2
        B = Get-Date
        C = 'Ipsum'
    }
    [PSCustomObject]@{
        A = 3
        B = $null
        C = 'Lorem Ipsum'
    }
)

# with headers
PS> ConvertTo-Delimited $Data
A|B|C
1|7/17/19 9:07:23 PM|Lorem
2|7/17/19 9:07:23 PM|Ipsum
||

# without headers
PS> ConvertTo-Delimited $Data -ExcludeHeader
1|7/17/19 9:08:19 PM|Lorem
2|7/17/19 9:08:19 PM|Ipsum
||

嗯,我的mac电脑上有Powershell 7 preview 1,导出Csv有一个-UseQuotes选项,您可以将其设置为“从不”。

一旦文件生成,您就可以运行

set-content FILENAME.csv ((get-content FILENAME.csv) -replace '"')

JPBlanc回答的一个稍加修改的变体:

我有一个现有的csv文件,如下所示:

% {$_ -replace  `
    '\G(?<start>^|,)(("(?<output>[^,"]*?)"(?=,|$))|(?<output>".*?(?<!")("")*?"(?=,|$))|(?<output>))', `
    '${start}${output}'}
001,002,003
004,005,006
Import-Csv -Path .\source.csv -Delimiter ',' -Header A,B,C | select A,C | ConvertTo-Csv -NoTypeInformation -Delimiter ',' | % {$_ -replace '"',''} | Out-File -Encoding utf8 .\target.csv
我只想将第一列和第三列导出到一个新的csv文件。当然,我不想要任何引号;-) 可以这样做:

% {$_ -replace  `
    '\G(?<start>^|,)(("(?<output>[^,"]*?)"(?=,|$))|(?<output>".*?(?<!")("")*?"(?=,|$))|(?<output>))', `
    '${start}${output}'}
001,002,003
004,005,006
Import-Csv -Path .\source.csv -Delimiter ',' -Header A,B,C | select A,C | ConvertTo-Csv -NoTypeInformation -Delimiter ',' | % {$_ -replace '"',''} | Out-File -Encoding utf8 .\target.csv

找不到类似问题的答案,所以我在这里发布我的发现

对于导出为管道分隔的且字符串限定符不带引号的
,请使用以下命令:

$objtable | convertto-csv -Delimiter "|" -notypeinformation | select -Skip $headers | % { $_ -replace '"\|"', "|"} | % { $_ -replace '""', '"'} | % { $_ -replace "^`"",''} | % { $_ -replace "`"$",''} | out-file "$OutputPath$filename" -fo -en ascii

这是我唯一能够处理文本中引号和逗号的方法;特别是在文本字段的开头或结尾处引号和逗号相邻的方法。

此函数从管道中获取powershell csv对象,并输出convertto csv等内容,但不添加引号(除非需要)

$names获取一个noteproperty名称数组,$values获取一个noteproperty值数组。它采取了那个特殊步骤来输出头。进程块一次获取一个csv对象

这里是一个测试运行

$delimiter = ','; $csvData = @"
id,string,notes,"points per 1,000",number
4,"a delimiter$delimiter is in here,","test data 3",1,348
5,"a comma, is in here,","test data 4`r`nwith a newline",0.5,347
6,hello world2.,classic,"3,000",123
"@

$csvdata | convertfrom-csv | sort number | convertto-unquotedcsv -delimiter $delimiter

id,string,notes,"points per 1,000",number
6,hello world2.,classic,"3,000",123
5,"a comma, is in here,","test data 4
with a newline",0.5,347
4,"a delimiter, is in here,",test data 3,1,348

以下是另一种方法:

Get-Process | ConvertTo-Csv -NoTypeInformation -Delimiter "," | 
    foreach { $_ -replace '^"|"$|"(?=,)|(?<=,)"','' }
Get Process | ConvertTo Csv-NoTypeInformation-Delimiter“,”

foreach{$|-replace'^“|”$|“(?=,)|(?如果您正在处理的数据被引用,因为它包含分隔符,则此项不起作用。请注意,这也会删除包含行分隔符的单元格的引号,\r\n将指定答案包含来自@LCC的建议。这可能不适用于
get process
的输出,但此解决方案还将取消包含以下内容的scape字段:它们中包含特殊字符(如“aaa”、“bbb”、“cc、cc”、“ddd”)@SteveGuidi您的回答是对的,它写在答案中。我仍然使用它获取引号。我不确定解决方法是什么。在OP问题中,除了从文件中删除引号之外,还有什么其他方法吗?这应该是答案。谢谢您,如果我有一个CSV行,其中包含三个参数,如
“123”、“Sanchez,Rick”、“Scientist”
,t