我有一些代码可以从字符串中转义双引号,其中可能包含预先转义的引号; e.g:
This is a \"string"
在Ruby 1.8.7p374中使用以下代码:
string.gsub!(/([^\\])"/, '\1\"')
但是,在以下字符串上尝试时,我得到了一些有趣的边缘情况:ab""c
=> ab\""c
。我希望它能逃脱两个引号。
这绝对不是一个大问题,但它让我很好奇
这是我的表达错误吗?一个gsub
错误/功能?
(在较新的Ruby版本中,这可能很容易通过使用负面回顾来解决,但在这个版本中似乎不支持它们。)
答案 0 :(得分:3)
要求匹配非\
字符意味着正则表达式需要使用该字符以及引号。 gsub
匹配也不能重叠。
你是正确的,后面的断言会解决这个问题。但是如果没有它,你可以在Ruby 1.8.7中有几个选择。
重复直到没有替换为止(gsub!
如果没有匹配则返回nil
):
loop { break unless string.gsub!(/([^\\])"/, '\1\"') }
对于1.8.7,您不会有后瞻性断言。但是你可以反转字符串,使用 look-ahead 断言进行更改,然后将其反转:
string = string.reverse.gsub(/"(?!\\)/, '"\\').reverse
答案 1 :(得分:2)
如果字符串的 start 中有引号,那么正则表达式也不起作用,例如"ab""c
将转换为"ab\""c
。其原因类似于双引号的情况。
gsub
匹配b"
并替换后,它会从上一场比赛继续,查看下一个"
,但不会查看之前消费的字符。
您可能能够在较新的Ruby版本中使用lookbehind修复您的问题,但这不会解决字符串问题的开始。解决这个问题的方法是使用\G
anchor(在Ruby 1.8.7中可用),它匹配上一个匹配结束的位置或字符串的开头。因此,在非斜杠或位于当前匹配开头(即"
之后,您正在寻找 的"
刚刚匹配或这是字符串的开头)。像这样:
string.gsub!(/([^\\]|\G)"/, '\1\"')
这会将字符串"ab""c
转换为\"ab\"\"c
。