如何在捕获的组之前跳过反斜杠?
例:
"foo+bar".gsub(/(\+)/, '\\\1')
Run Code Online (Sandbox Code Playgroud)
我期望(和想要):
foo\+bar
Run Code Online (Sandbox Code Playgroud)
我不幸得到的:
foo\\1bar
Run Code Online (Sandbox Code Playgroud)
我该如何正确逃离?
正如其他人所说,你需要两次逃脱该字符串中的所有内容.所以在你的情况下,解决方案是使用'\\\\\1'或'\\\\\\1'.但既然你问为什么,我会试着解释那个部分.
原因是替换序列被解析两次 - 一次是Ruby,一次是底层正则表达式引擎,对象\1是自己的转义序列.(它可能更容易与双引号字符串理解,因为单引号引进的不确定性,其中'\\1'和'\1'是等价的,但'\'并'\\'没有.)
因此,例如,这里使用捕获的组和双引号字符串进行简单替换将是:
"foo+bar".gsub(/(\+)/, "\\1") #=> "foo+bar"
Run Code Online (Sandbox Code Playgroud)
这将字符串传递\1给regexp引擎,它将其理解为对捕获组的引用.在Ruby字符串文字中,"\1"完全意味着其他东西(ASCII字符1).
在这种情况下我们真正想要的是regexp引擎接收\\\1.它也被理解\为一个转义字符,因此\\1是不够的,只是简单地评估字面输出\1.因此,我们需要\\\1在regexp引擎中,但要达到这一点,我们还需要使它通过Ruby的字符串文字解析器.
为此,我们采用所需的regexp输入并再次加倍每个反斜杠以通过Ruby的字符串文字解析器.\\\1因此需要"\\\\\\1".在单引号的情况下,可以省略一个斜杠,因为\1它不是单引号中的有效转义序列,而是按字面处理.
这个问题通常被隐藏的原因之一是由于使用了/.+/样式正则表达式引用,Ruby以一种特殊的方式处理,以避免双重逃避所有内容.(当然,这不适用于gsub替换字符串.)但是如果在以下位置使用字符串文字而不是regexp文字,您仍然可以看到它的运行情况Regexp.new:
Regexp.new("\.").match("a") #=> #<MatchData "a">
Regexp.new("\\.").match("a") #=> nil
Run Code Online (Sandbox Code Playgroud)
正如你所看到的,我们必须要仔细逃脱.它被理解为文字.由正则表达式引擎,因为"."和"\."这两个评估以.在双引号字符串,但我们需要发动机本身接收\..
| 归档时间: |
|
| 查看次数: |
1738 次 |
| 最近记录: |