如何在许多匹配项中使用 ruby gsub Regexp?
Posted
技术标签:
【中文标题】如何在许多匹配项中使用 ruby gsub Regexp?【英文标题】:How to use ruby gsub Regexp with many matches? 【发布时间】:2012-02-24 07:21:19 【问题描述】:我的 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")
但没用
【问题讨论】:
【参考方案1】:您的正则表达式需要更粗一些,以防引号出现在第一个值的开头或最后一个值的结尾:
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 中可用的否定后向和否定前瞻断言(锚)。
(?<!^|,)
— 在此位置之前不得有行首 (^
) 或逗号
"
— 查找双引号
(?!,|$)
— 紧随此位置后不得有逗号或行尾 ($
)
作为奖励,由于您实际上并未捕获任一侧的字符,因此您无需担心在替换字符串中正确使用 \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')
【讨论】:
酷,我试图弄清楚如何在 Ruby 中进行负面的后向断言,但无法弄清楚。 感谢 Phrogz,它仅适用于 ruby 1.9,您能建议 ruby 1.8 的答案吗? @MahmoudKhaled 已更新为与 Ruby 1.8 一起使用。 (将来,如果您需要如此古老的 Ruby 版本,请在您的问题中包含此内容。Ruby 1.9.1 — 1.9 系列的第一个稳定版本 — 发布了三年 以前。) @Rivenfall 正确。这就是我所说的:“你不能在替换字符串中使用字符串插值”。您的意思是对原始问题发表评论吗?还是您误读了这个答案? 对不起,我误读了答案。我将添加 \0 是输入字符串(但不是 $0)【参考方案2】:假设s
是一个字符串,这将起作用:
puts s.gsub(/([^,])"([^,])/, "\\1\"\"\\2")
【讨论】:
当您在内容中使用双引号时,最好使用单引号将它们括起来,如'\1""\2'
或使用第三种形式%q[\1""\2]
我有点担心我的答案实际上不足以满足您的情况,因为它无法处理很多事情,例如您的引号旁边是否真的有逗号数据。您可能需要做一些不基于正则表达式的更复杂的事情。以上是关于如何在许多匹配项中使用 ruby gsub Regexp?的主要内容,如果未能解决你的问题,请参考以下文章