ruby - 如何在许多匹配项中使用 ruby​​ gsub Regexp?

标签 ruby regex csv gsub string-substitution

我的 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 = <<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 中可用的负向后视和负向前向断言( anchor )。

  • (?<!^|,) — 在此点之前不得有行首 ( ^ ) 或逗号
  • " — 找到双引号
  • (?!,|$) — 在此点之后不能有逗号或行尾 ($)

作为奖励,由于您实际上并没有捕获任何一侧的字符,因此您无需担心使用 \1在您的替换字符串中正确。

有关详细信息,请参阅 official Ruby regex documentation 中的“ anchor ”部分.


但是,如果您确实需要替换输出中的匹配项,您可以使用以下任一方法:

"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 的 block 形式为每个匹配重新调用 block ,此时全局 $1已适当填充并可供使用。


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

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

关于ruby - 如何在许多匹配项中使用 ruby​​ gsub Regexp?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9098759/

相关文章:

ruby - 有没有办法从 Ruby 中的图像 URL 检索上次修改日期?

java - 替换两个字符串之间的字符串

python - 奇怪的 JSON 到 CSV 的转换

linux - 如何在 bash 中对逗号分隔值进行排序?

python - 如何从电子邮件中获取 csv 附件并保存

ruby - 如何按不同顺序的多个条件进行排序?

css - Rails 3.1 中的 CSS 样式有什么问题?

ruby-on-rails - #<Stripe::ListObject 的 Stripe 未定义方法 `create':

java - 解析日志文件以提取查询

regex - MongoDb 未在查询说明符中注册字段