带有字符串“+”的 Ruby 方法 gsub

PRD*_*RSD 0 ruby methods gsub

我在红宝石中发现了有趣的事情。有人知道为什么是行为吗?

'+'.gsub!('+', '/+')

尝试'+'.gsub!('+', '\+')并预期 "\\+"但得到""(空字符串)

Sil*_*olo 6

gsub在一些间接之后实现,如rb_sub_str_bang在 C 中,它调用rb_reg_regsub.

现在,gsub应该允许替换字符串包含反向引用。也就是说,如果您传递一个正则表达式作为第一个参数,并且该正则表达式定义了一个捕获组,那么您的替换字符串可以包含\1以指示该捕获组应放置在该位置。

如果您传递普通的非正则表达式字符串作为模式,这种行为显然仍然会发生。您的逐字字符串显然不会有任何捕获组,因此在这种情况下有点愚蠢。但是,例如,尝试替换字符串中的+with将给出空字符串,因为表示要获取第一个捕获组,该捕获组不存在,因此是 vacously 。\1+\1""

现在,您可能会想:+这不是一个数字。你是对的。你要替换+\+. 替换字符串中还允许其他几个反向引用。我找不到任何记录这些内容的官方文档,但源代码做得很好。总结一下代码:

  • 数字\1\9指的是编号的捕获组。
  • \k<...>指已命名的捕获组,名称位于尖括号中。
  • \0\&引用匹配的整个子字符串,因此(\0)替换字符串会将匹配项括在括号中。
  • 反斜杠后跟反引号(我不知道如何使用 StackOverflow 的 markdown 来编写它)指的是匹配之前的整个字符串。
  • \'指匹配之后的整个字符串。
  • \+指的是最终的捕获组,即编号最大的捕获组。
  • \\是一个字面上的反斜杠。

(其中大部分都是基于类似名称的 Perl 变量)

所以,在你的例子中,

  • \+正如替换字符串所说“获取最后一个捕获组”。没有捕获组,因此您得到空字符串。
  • \-不是有效的反向引用,因此它被逐字替换。
  • \ok同样,不是反向引用,因此它被逐字替换。
  • 在 中\\+,Ruby 吃掉第一个反斜杠序列,因此运行时的实际字符串是\+,相当于第一个示例。
  • 对于\\\+,Ruby 处理第一个反斜杠序列,因此我们可以\\+在替换函数看到它时得到它。\\是一个字面上的反斜杠,并且+不再是转义序列的一部分,所以我们得到\+.