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 :(得分:17)
你被\'
inside a regular expression replacement string的特殊性绊倒了:
\0
,\1
,\2
,...\9
,\&
,\`
,\'
,\+
替换第n个分组子表达式匹配的值,或者整个匹配,匹配前或匹配后或最高组。
因此,当您说"\\'"
时,双\\
只会变为一个反斜杠,结果为\'
,但这意味着“上一次成功匹配右侧的字符串”。如果您想要使用转义单引号替换单引号,则需要转义更多以超越\'
的特殊性:
s.gsub("'", "\\\\'")
或者避免使用牙签并使用阻止形式:
s.gsub("'") { |m| '\\' + m }
如果你试图逃避反引号,加号,甚至是一个数字,你会遇到类似的问题。
这里的总体教训是,除了最微不足道的替换外,我更喜欢block form of gsub
。
答案 1 :(得分:2)
s = "#main = 'quotes'
s.gsub "'", "\\\\'"
由于\
它是\\
等效的,如果你想得到一个双反斜杠,你必须放四个。
答案 2 :(得分:1)
您还需要逃避\:
s.gsub "'", "\\\\'"
输出
"#main= \\'quotes\\'"
在外部论坛上发现一个很好的解释:
理解恕我直言的关键是反斜杠是特别的 替换字符串。所以,每当有人想要一个文字时 替换字符串中的反斜杠需要逃避它,因此 有[两个]反斜杠。巧合的是,反斜杠在a中也很特别 字符串(即使在单引号字符串中)。所以你需要两个级别 转义,在屏幕上为一个文字制作2 * 2 = 4个反斜杠 替换反斜杠。