为什么String#gsub会双重内容?

s = "#main= 'quotes' s.gsub "'", "\\'" # => "#main= quotes'quotes" 

这似乎是错误的,我希望得到"#main= \\'quotes\\'"

当我不使用转义字符时,它按预期工作。

 s.gsub "'", "*" # => "#main= *quotes*" 

所以必须与逃避有关。

使用ruby 1.9.2p290

我需要用反斜杠和引号替换单引号。

更多的不一致:

 "\\'".length # => 2 "\\*".length # => 2 # As expected "'".gsub("'", "\\*").length # => 2 "'a'".gsub("'", "\\*") # => "\\*a\\*" (length==5) # WTF next: "'".gsub("'", "\\'").length # => 0 # Doubling the content? "'a'".gsub("'", "\\'") # => "a'a" (length==3) 

这里发生了什么?

你正在被正则表达式替换字符串中的特殊性绊倒:

\0\1\2 ,… \9\&\`\'\+
替换第n个分组子表达式匹配的值,或者整个匹配,前匹配或后匹配或最高组。

所以当你说"\\'" ,双\\只会变成一个反斜杠,结果就是\'但这意味着“最后一次成功匹配右边的字符串”。 如果要使用转义单引号替换单引号,则需要转义更多以超越\'的特殊性:

 s.gsub("'", "\\\\'") 

或者避免牙签并使用块forms:

 s.gsub("'") { |m| '\\' + m } 

如果你试图逃避反引号,加号或甚至一个数字,你会遇到类似的问题。

这里的总体教训是更喜欢gsub的块forms,除了最简单的替换。

 s = "#main = 'quotes' s.gsub "'", "\\\\'" 

因为\它是等同的,如果你想得到一个双反斜杠你必须放四个。

你还需要逃脱\:

 s.gsub "'", "\\\\'" 

输出

 "#main= \\'quotes\\'" 

在外部论坛上发现一个很好的解释:

理解IMHO的关键是反斜杠在替换字符串中是特殊的。 因此,每当想要在替换字符串中使用字面反斜杠时,就需要将其转义,因此有两个反斜杠。 巧合的是,反斜杠在字符串中也很特殊(即使在单引号字符串中)。 所以你需要两个级别的转义,在屏幕上制作2 * 2 = 4个反斜杠,用于一个文字替换反斜杠。

资源