首页 文章

为什么String#gsub会双重内容?

提问于
浏览
9
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)

这里发生了什么?

3 回答

  • 17

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

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

    所以当你说 "\\'" 时,双 \\ 变成一个反斜杠,结果是 \' 但这意味着"The string to the right of the last successful match."如果你想用单引号替换单引号,你需要逃避更多以超越 \' 的特殊性:

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

    或者避免牙签并使用块形式:

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

    如果你试图逃避反引号,加号或甚至一个数字,你会遇到类似的问题 .

    这里的总体教训是,除了最微不足道的替换之外,更喜欢block form of gsub .

  • 2

    你还需要逃脱\:

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

    输出

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

    在外部论坛上发现一个很好的解释:

    理解IMHO的关键是反斜杠在替换字符串中是特殊的 . 因此,每当想要在替换字符串中使用字面反斜杠时,就需要将其转义,因此有[两个]反斜杠 . 巧合的是,反斜杠在字符串中也很特殊(即使在单引号字符串中) . 因此,您需要两个级别的转义,在屏幕上制作2 * 2 = 4个反斜杠,以获得一个文字替换反斜杠 .

    source

  • 1
    s = "#main = 'quotes'
    
    s.gsub "'", "\\\\'"
    

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

相关问题