如何使用ruby gsub Regexp与许多匹配?

我的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}") 

但没有奏效

如果引号出现在第一个值的开头或最后一个值的末尾,则正则表达式需要更加粗体:

 csv = < 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

有关更多信息,请参阅官方Ruby regex文档中的“Anchors”部分。


但是,对于需要替换输出中的匹配项的情况,可以使用以下任何一种方法:

 "hello".gsub /([aeiou])/, '<\1>' #=> "hll" "hello".gsub /([aeiou])/, "<\\1>" #=> "hll" "hello".gsub(/([aeiou])/){ |m| "<#{$1}>" } #=> "hll" 

您不能像替换字符串那样在替换字符串中使用字符串插值:

 "hello".gsub /([aeiou])/, "<#{$1}>" #=> "hll" 

...因为字符串插值在gsub运行之前发生过一次。 使用gsub的块forms重新调用每个匹配的块,此时全局$1已被适当填充并可供使用。


编辑 :对于Ruby 1.8(为什么你在使用它?)你可以使用:

 puts csv.gsub(/([^,\n\r])"([^,\n\r])/,'\1""\2') 

假设s是一个字符串,这将起作用:

 puts s.gsub(/([^,])"([^,])/, "\\1\"\"\\2")