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

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

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

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

所以逃跑肯定是有关系的。

使用红宝石 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)

这里发生了什么?

4

3 回答 3

19

您被\'正则表达式替换字符串内部的特殊性绊倒了:

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

因此,当您说 时"\\'",双\\精度变成了一个反斜杠,结果是\'但这意味着“最后一次成功匹配右侧的字符串”。如果你想用转义的单引号替换单引号,你需要转义更多以克服特殊性\'

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

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

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

如果您试图避开反引号、加号甚至单个数字,您会遇到类似的问题。

这里的整体教训是,除了最微不足道的替换之外,更喜欢块形式的任何东西。gsub

于 2011-08-16T07:13:20.623 回答
3
s = "#main = 'quotes'

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

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

于 2011-08-16T06:36:16.410 回答
2

您还需要转义 \ :

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

输出

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

在外部论坛上找到了一个很好的解释:

理解恕我直言的关键是反斜杠在替换字符串中是特殊的。因此,每当想要在替换字符串中使用文字反斜杠时,都需要对其进行转义,因此需要使用 [两个] 反斜杠。巧合的是,反斜杠在字符串中也很特殊(即使在单引号字符串中)。因此,您需要两级转义,在屏幕上生成 2 * 2 = 4 个反斜杠,以换取一个文字替换反斜杠。

来源

于 2011-08-16T06:36:37.527 回答