反斜杠+;Ruby正则表达式中捕获的组

反斜杠+;Ruby正则表达式中捕获的组,ruby,regex,Ruby,Regex,如何在捕获的组之前删除反斜杠 例如: "foo+bar".gsub(/(\+)/, '\\\1') 我所期望的(和想要的): 我不幸得到的是: foo\\1bar 如何在这里正确转义?再添加两次\将正确转义 irb(main):011:0> puts "foo+bar".gsub(/(\+)/, '\\\\\1') foo\+bar => nil 这是由于双字符串转义造成的。在这种情况下,您应该使用5个斜杠 "foo+bar".gsub(/([+])/, '\\\\\1')

如何在捕获的组之前删除反斜杠

例如:

"foo+bar".gsub(/(\+)/, '\\\1')
我所期望的(和想要的):

我不幸得到的是:

foo\\1bar

如何在这里正确转义?

再添加两次
\
将正确转义

irb(main):011:0> puts "foo+bar".gsub(/(\+)/, '\\\\\1')
foo\+bar
=> nil

这是由于双字符串转义造成的。在这种情况下,您应该使用5个斜杠

"foo+bar".gsub(/([+])/, '\\\\\1')

正如其他人所说的那样,你需要两次逃避这个字符串中的所有内容。因此,在您的案例中,解决方案是使用
'\1'
'\1'
。但既然你问了为什么,我就试着解释一下

原因是替换序列被解析了两次——一次由Ruby解析,一次由底层正则表达式引擎解析,
\1
是它自己的转义序列。(使用双引号字符串可能更容易理解,因为单引号会引入歧义,其中
'\\1'
'\1'
是等效的,但
'\'
'\\'
不是。)

例如,这里用一个捕获的组和一个双引号字符串进行简单替换:

"foo+bar".gsub(/(\+)/, "\\1")   #=> "foo+bar"
这将字符串
\1
传递给regexp引擎,它将其理解为对捕获组的引用。在Ruby字符串文本中,
“\1”
表示完全不同的含义(ASCII字符1)

在这种情况下,我们实际上希望regexp引擎接收
\\\1
。它还将
\
理解为转义字符,因此
\\1
是不够的,只需计算文本输出
\1
。因此,我们需要在regexp引擎中使用
\\\1
,但要达到这一点,我们还需要让它通过Ruby的字符串文本解析器

为此,我们获取所需的regexp输入并再次加倍每个反斜杠,以通过Ruby的字符串文本解析器<代码>\\\1因此需要
“\1”
。在单引号的情况下,可以省略一个斜杠,因为
\1
在单引号中不是有效的转义序列,而是按字面处理的

补遗 这个问题通常被隐藏的原因之一是由于使用了
/.+/
风格的regexp引号,Ruby以一种特殊的方式处理它,以避免双重转义。(当然,这不适用于
gsub
替换字符串。)但如果在
regexp.new
中使用字符串文字而不是regexp文字,您仍然可以看到它的作用:

Regexp.new("\.").match("a")   #=> #<MatchData "a">
Regexp.new("\\.").match("a")  #=> nil
Regexp.new(“\”).match(“a”)#=>#
Regexp.new(“\\”).match(“a”)\=>nil

如您所见,我们必须对
进行双重转义,才能让regexp引擎将其理解为文本
,因为
”\。
在双引号字符串中计算为
,但是我们需要引擎本身来接收
\。

你能解释一下这里发生了什么,为什么需要5个吗?这个让我抓狂!
Regexp.new("\.").match("a")   #=> #<MatchData "a">
Regexp.new("\\.").match("a")  #=> nil