我有以下文件格式的.csv:
In: "bob","1234 Main St, New York, NY","cool guy"
我希望删除内部没有逗号的双引号:
Out: bob,"1234 Main St, New York, Ny",cool guy
有没有办法在Powershell中做到这一点?
我查了一下:
答案 0 :(得分:3)
调整"How to remove double quotes on specific column from CSV file using Powershell script"的代码:
$csv = 'C:\path\to\your.csv'
(Get-Content $csv) -replace '(?m)"([^,]*?)"(?=,|$)', '$1' |
Set-Content $csv
正则表达式(?m)"([^,]*?)"(?=,|$)
匹配任何" + 0 or more non-commas + "
之前逗号或行尾(通过正向前瞻和多行选项(?m)
实现强制$
匹配换行符,而不仅仅是字符串的结尾。
请参阅regex demo
答案 1 :(得分:1)
我不确切地知道你脚本的其余部分是什么样的。尝试沿着这些方向尝试
(("bob","1234 Main St, New York, NY","cool guy") -split '"' |
ForEach-Object {IF ($_ -match ",") {'"' + $_ + '"' } ELSE {$_}}) -join ","
答案 2 :(得分:1)
在 PowerShell [Core] v7 + 中,您现在可以将-UseQuotes AsNeeded
与ConvertTo-Csv
和Export-Csv
一起使用,这大大简化了方法:
@'
Name,Address,Comment
"bob","1234 Main St, New York, NY","cool guy"
'@ | ConvertFrom-Csv |
ConvertTo-Csv -UseQuotes AsNeeded # use Export-Csv to save to a file.
上面的代码产生了以下内容,表明只有带有嵌入式,
的字段才被双引号引起来:
Name,Address,Comment
bob,"1234 Main St, New York, NY",cool guy
-UseQuotes
接受AsNeeded
,Always
和Newer
另外,还有-QuoteFields
,它接受列(属性)名称的数组 (应有选择地使用引号)。
答案 3 :(得分:0)
现有答案适用于样本输入:
,
的双引号字段,首先将整个输入文件加载到内存中,这样就可以将输入文件替换为单个管道中的结果。"
字符将行拆分为字段,是大型输入文件的替代方法,因为它使用管道逐个处理输入行。如果我们 概括 OP要求处理嵌入式"
字符 的字段,我们需要采用不同的方法:
以下字段必须保留其封闭的双引号:
,
字符的双引号字段。例如,"1234 Main St, New York, NY"
"
字符的双引号字段,每个RFC 4180必须转义为""
,即加倍;例如,"Nat ""King"" Cole"
注意:
- 我们不处理可能包含嵌入式换行符的字段,因为这需要一种根本不同的方法,因为自包含的逐行处理是没有的更长的时间。
- Wiktor Stribiżew的提示,提出正则表达式以强制匹配双引号字段与任意数量的嵌入式双引号,转义为""
:"([^"]*(?:""[^"]*)*)"
# Create sample CSV file with double-quoted fields that contain
# just ',', just embedded double quotes ('""'), and both.
@'
bob,"1234 Main St, New York, NY","cool guy"
nat,"Nat ""King"" Cole Lane","cool singer"
nat2,"Nat ""King"" Cole Lane, NY","cool singer"
'@ | Set-Content ./test.csv
Get-Content ./test.csv | ForEach-Object {
# Match all double-quoted fields on the line, and replace those that
# contain neither commas nor embedded double quotes with just their content,
# i.e., with enclosing double quotes removed.
([regex] '"([^"]*(?:""[^"]*)*)"').Replace($_, { param($match)
$fieldContent = $match.Groups[1]
if ($fieldContent -match '[,"]') { $match } else { $fieldContent }
})
}
这会产生:
bob,"1234 Main St, New York, NY",cool guy
nat,"Nat ""King"" Cole Lane",cool singer
nat2,"Nat ""King"" Cole Lane, NY",cool singer
更新输入文件:
与markg的答案一样,由于逐行处理,您无法直接使用同一管道中的输出更新输入文件。
要在以后更新iput文件,请使用临时输出文件,然后用它替换输入文件(...
代表上面的Get-Content
管道,仅使用$csvFile
代替./test.csv
}):
$csvfile = 'c:\path\to\some.csv'
$tmpFile = $env:TEMP\tmp.$PID.csv
... | Set-Content $tmpFile
if ($?) { Move-Item -Force $tmpFile $csvFile }
请注意,Set-Content
默认使用系统的单字节扩展ASCII字符编码(即使help topic falsely states ASCII)。
使用-Encoding
参数可以指定不同的编码,但请注意,Out-File
/ >
的默认值UTF-16LE会导致无法识别CSV文件例如,通过Excel正确使用。