【问题标题】:Why does String#gsub double content?为什么 String#gsub 会加倍内容?
【发布时间】:2011-10-27 19:25:27
【问题描述】:
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)

这是怎么回事?

【问题讨论】:

标签: ruby-on-rails ruby regex gsub


【解决方案1】:

你被 \' inside a regular expression replacement string 的特殊性绊倒了:

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

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

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

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

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

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

这里的总体教训是,除了最琐碎的替换之外,更喜欢 block form of gsub

【讨论】:

  • 非常感谢。它肯定会清除这些东西。我只是想知道替换 \&, `, \', \+ 是什么意思?我不记得我曾在任何地方看到过它们。
  • @Dmytrii:查看这些的全局变量版本可能会有所帮助 (zenspider.com/Languages/Ruby/QuickRef.html#19)。我不知道 Ruby 的正则表达式有什么好的权威在线参考。
【解决方案2】:
s = "#main = 'quotes'

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

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

【讨论】:

  • 我不想要双反斜杠 - 只有一个。这就是为什么我转义一个斜线并添加引号。 "\\'".length == 2 是正确的。 gsub 把内容加倍弄错了。
【解决方案3】:

您还需要转义 \:

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

输出

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

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

理解恕我直言的关键是反斜杠在 替换字符串。所以,每当一个人想要一个字面量 替换字符串中的反斜杠需要对其进行转义,因此 有 [两个] 反斜杠。巧合的是,反斜杠在 字符串(即使在单引号字符串中)。所以你需要两个级别 转义,在屏幕上为一个文字生成 2 * 2 = 4 个反斜杠 替换反斜杠。

source

【讨论】:

  • 但它已经被转义了 - 字符串 "\\" 应该返回一个斜杠。那么"\\'" 返回长度等于 2 的字符串:第一个是斜杠,第二个是引号。它在 gsub 中搞砸了,因为它使内容加倍(为什么?)。
  • 另外.gsub("'", "\\*") 按预期工作,这更加不一致。
  • 问题是 \' has a special meaning 在正则表达式替换中,这个有点模糊的功能主要是出于历史原因。
猜你喜欢
  • 1970-01-01
  • 2022-11-01
  • 1970-01-01
  • 1970-01-01
  • 2017-10-05
  • 1970-01-01
  • 1970-01-01
  • 2018-05-29
  • 1970-01-01
相关资源
最近更新 更多