Barras de barriga em Gsub (escapando e backreferencing)
-
26-09-2019 - |
Pergunta
Considere o seguinte snippet:
puts 'hello'.gsub(/.+/, '\0 \\0 \\\0 \\\\0')
Isso impressa (Como visto em ideone.com):
hello hello \0 \0
Isso foi muito surpreendente, porque eu esperaria ver algo assim:
hello \0 \hello \\0
Meu argumento é que \
é um personagem de fuga, então você escreve \\
para obter uma barra de barra literal, assim \\0
é uma barra de barra literal \
Seguido por 0
, etc. Obviamente não é assim gsub
É interpretá -lo, então alguém pode explicar o que está acontecendo?
E o que preciso fazer para obter a substituição que quero acima?
Solução
A fuga é limitada ao usar citações únicas, em vez de citações duplas:
puts 'sinlge\nquote'
puts "double\nquote"
"\0"
é o caractere nulo (usado ie em c para determinar o fim de uma string), onde como '\0'
é "\\0"
, portanto, ambos 'hello'.gsub(/.+/, '\0')
e 'hello'.gsub(/.+/, "\\0")
Retorna "hello"
, mas 'hello'.gsub(/.+/, "\0")
retorna "\000"
. Agora 'hello'.gsub(/.+/, '\\0')
retornando 'hello'
Ruby está tentando lidar com os programadores que não mantêm a diferença entre aspas simples e duplas em mente. De fato, isso não tem nada a ver com gsub
: '\0' == "\\0"
e '\\0' == "\\0"
. Seguindo essa lógica, o que você possa pensar, é assim que Ruby vê as outras cordas: ambos '\\\0'
e '\\\\0'
igual "\\\\0"
, que (quando impresso) te dá \\0
. Como o GSUB usa \x
Para inserir o número da correspondência X, você precisa de uma maneira de escapar \x
, qual é \\x
, ou em sua representação de string: "\\\\x"
.
Portanto, a linha
puts 'hello'.gsub(/.+/, "\\0 \\\\0 \\\\\\0 \\\\\\\\0")
de fato resulta em
hello \0 \hello \\0