问题描述
有一些字段,其中可以有多个双引号。我想用额外的双引号来转义它们。
","ABC "XYZ" PQRS","
","ABC "XYZ"","ABC "A" "B" 测试","ABC 2.5" "C" 测试","
我得到了 link 的帮助,并且能够使用正则表达式 [regex]$r='(","[^"]+"[^"]+?",")'
覆盖内容中包含单双引号的场景。但是,在内容中有多个双引号的情况下会被卡住。
[regex]$r='(","[^"]+"[^"]+"",")' # Not working
get-content C:\Projects\MyProject\testRegexFordoublequotes.csv | foreach {
#save each line to a variable to make it easier to track
$line=$_
#look for a regex match
$find=$r.matches($line)
if ($find[0].Success) {
foreach ($match in $find) {
#the original string we matched on
$found=$match.value
#replace the substring
$replace= '","'+ $found.Trim('","').Replace('""','"').Replace('"','""')+ '","'
#replace the full string and write to the pipeline
$line -replace $found,$replace
} #foreach
} #if
else {
#no match so write the line to pipeline
$line
}
} | Set-Content C:\Projects\MyProject\modified.csv -Force
你能帮我定义正则表达式吗,这将有助于字段内的多个双引号。
解决方法
搜索有效分隔符(例如"\s*,\s*"
)并将您的行拆分为字段可能更容易,而不是简单地用 2 个引号更正每个(无效)单双引号每个领域。
通过用双引号将字段括起来并用 csv
(逗号)分隔符将它们连接起来,将字段重建为记录
输入
$Csv = @'
"Field","ABC "XYZ" PQRS","Field"
"Field","ABC "XYZ"","ABC "A" "B" TEST","ABC 2.5" "C" Test","Field"
'@ -Split '[\r\n]+'
脚本
$Csv | # replace with: get-content .\testRegexFordoublequotes.csv |
Foreach-Object {
$Line = $_ -Replace '^\s*"' -Replace '"\s*$' # Strip outer double quotes
$Fields = $Line -Split '"\s*,\s*"' # Split line into fields
$Fields = $Fields -Replace '"','""' # Escape each " in each field
'"' + ($Fields -Join '","') + '"' # Rejoin the fields to line
} # append: | Set-Content .\modified.csv -Force
输出
"Field","ABC ""XYZ"" PQRS","ABC ""XYZ""","ABC ""A"" ""B"" TEST","ABC 2.5"" ""C"" Test","Field"
,
根据我们在帖子评论中的对话,这些文件是不符合标准的 CSV 文件,因此 CSV 解析器没有帮助。
请注意,如果单个单元格碰巧有 some textext","more text
,则您将遇到未定义的情况。由于未转义引号,该单元格将被视为两个单元格。
现在到正则表达式。你可以找到一个带有前瞻和后视的正则表达式,但我认为盲目地将所有引号加倍,然后清理意外的引号更容易,例如在行首和行尾,以及单元格之间。
我不熟悉 powershell,但这里有一段 JavaScript/伪代码,您可以轻松地将其转换为 powershell 语法。我正在使用一行包含您声明的所有测试用例;您将遍历文件中的行:
/* assume $line is:
"Start","End"
*/
$fixed = $line.replace(/"/g,'""')
.replace(/"",""/g,'","')
.replace(/^""/,'"')
.replace(/""$/,'"')
/* $fixed is:
"Start","End"
*/
说明:
-
.replace(/"/g,'""')
- 盲目地将所有引号加倍 -
.replace(/"","')
- 将"",""
恢复到","
-
.replace(/^""/,'"')
- 将行首的""
恢复为"
-
.replace(/""$/,'"')
- 将行尾的""
恢复为"
您可以执行以下操作以查看更改:
(Get-Content file.csv) -replace '(?<!^|",)"(?!,"|$)','""'
您可以简单地通过管道连接到 Set-Content
以保存新内容:
(Get-Content file.csv) -replace '(?<!^|",'""' |
Set-Content file.csv
说明:
(?<!^|",)
是对不是行首 (^
) 或 ",
的任何先前位置的否定后视。 (?!,"|$)
是对不是行尾 ($
) 或 ,"
的任何下一个位置的负前瞻。如果满足这些环视条件,"
将替换为 ""
。