我的csv文件内容在引用文本
中有双引号test,first,line,"you are a "kind" man",thanks
again,second,li,"my "boss" is you",good
我需要用“”
替换逗号前面或后面的每个双引号test,first,line,"you are a ""kind"" man",thanks
again,second,li,"my ""boss"" is you",good
所以“被”“
取代我试过
x.gsub(/([^,])"([^,])/, "#{$1}\"\"#{$2}")
但没有效果
答案 0 :(得分:43)
如果引号出现在第一个值的开头或最后一个值的末尾,那么你的正则表达式需要更加粗体:
csv = <<ENDCSV
test,first,line,"you are a "kind" man",thanks
again,second,li,"my "boss" is you",good
more,""Someone" said that you're "cute"",yay
"watch out for this",and,also,"this test case"
ENDCSV
puts csv.gsub(/(?<!^|,)"(?!,|$)/,'""')
#=> test,first,line,"you are a ""kind"" man",thanks
#=> again,second,li,"my ""boss"" is you",good
#=> more,"""Someone"" said that you're ""cute""",yay
#=> "watch out for this",and,also,"this test case"
上面的正则表达式使用Ruby 1.9中提供的负向lookbehind和负向前瞻断言(锚点)。
(?<!^|,)
- 紧接此点之前,不得有行首(^
)或逗号"
- 找一个双引号(?!,|$)
- 紧跟此点之后,不得有逗号或行尾($
)作为奖励,由于您实际上并未捕获任何一方的字符,因此您无需担心在替换字符串中正确使用\1
。
有关详情,请参阅official Ruby regex documentation中的“主持人”部分。
但是,对于做需要替换输出中的匹配项的情况,您可以使用以下任何一种方法:
"hello".gsub /([aeiou])/, '<\1>' #=> "h<e>ll<o>"
"hello".gsub /([aeiou])/, "<\\1>" #=> "h<e>ll<o>"
"hello".gsub(/([aeiou])/){ |m| "<#{$1}>" } #=> "h<e>ll<o>"
您不能像替换字符串那样在替换字符串中使用字符串插值:
"hello".gsub /([aeiou])/, "<#{$1}>"
#=> "h<previousmatch>ll<previousmatch>"
...因为字符串插值发生一次,之前 gsub
已经运行。使用gsub
的块形式为每个匹配重新调用块,此时全局$1
已被适当填充并可供使用。
编辑:对于Ruby 1.8(为什么要使用它?),您可以使用:
puts csv.gsub(/([^,\n\r])"([^,\n\r])/,'\1""\2')
答案 1 :(得分:9)
假设s
是一个字符串,这将起作用:
puts s.gsub(/([^,])"([^,])/, "\\1\"\"\\2")