2008-11-13 14 views
46

Al usar expresiones regulares en Ruby, ¿cuál es la diferencia entre $ 1 y \ 1?

Respuesta

78

\ 1 es una referencia hacia atrás, que sólo funcionará en el mismo sub o gsub llamada a un método, por ejemplo:

"foobar".sub(/foo(.*)/, '\1\1') # => "barbar" 

$ 1 es una variable global que se puede utilizar en código más tarde:

if "foobar" =~ /foo(.*)/ then 
    puts "The matching word was #{$1}" 
end 

Salida:

"The matching word was bar" 
# => nil 
+0

Tenga en cuenta que [el tratamiento de Ruby de las comillas simples versus las dobles] (http://stackoverflow.com/a/3028799/303896) puede interponerse en su camino al intentar usar referencias retrospectivas. – alxndr

+0

no entendí mucho, ¿puede alguien dar alguna explicación más? – YasirAzgar

+0

@YasirAzgar '.sub()' es una llamada a un método. ''\ 1'' puede (aparentemente) usarse solo dentro del alcance de una llamada a un método' sub' o 'gsub'. En el primer ejemplo, '" foobar ".sub (/ foo (. *) /, '\ 1 \ 1')', ''\ 1'' está dentro del alcance del método' sub'. En el segundo ejemplo, '$ 1' se referencia fuera de un método' sub'/'gsub'. El ejemplo muestra que se hace referencia poco después de una llamada '= ~', pero eso es irrelevante. Aparentemente, el uso de una expresión regular establece '$ 1', que, como variable global, se puede referenciar en cualquier lugar. – John

29

Tenga en cuenta que hay una tercera opción, la b forma de bloqueo de sub. A veces lo necesitas. Digamos que quiere reemplazar algún texto con el reverso de ese texto. No se puede utilizar $ 1 porque no está obligado con la suficiente rapidez:

"foobar".sub(/(.*)/, $1.reverse) # WRONG: either uses a PREVIOUS value of $1, 
            # or gives an error if $1 is unbound 

Tampoco se puede utilizar \1, ya que el método sub sólo lo hace un simple texto de sustitución de \1 con el texto apropiado capturado, no hay magia teniendo lugar aquí:

"foobar".sub(/(.*)/, '\1'.reverse) # WRONG: returns '1\' 

Así que si quieres hacer algo de fantasía, se debe utilizar la forma de bloques de sub ($ 1, $ 2, $ ', $', etc. estarán disponibles):

"foobar".sub(/.*/){|m| m.reverse} # => returns 'raboof' 
"foobar".sub(/(...)(...)/){$1.reverse + $2.reverse} # => returns 'oofrab' 
+1

Su ejemplo podría ser engañoso: la coincidencia es lo que se transfiere al bloque, no los grupos de coincidencia. Entonces, si quisieras cambiar "foobar" por "foorab", tendrías que hacer 'str.sub (/ (foo) (\ w +) /) {$ 1 + $ 2.reverse}' – rampion

+1

Ver ri String # sub : En el formulario de bloque, la cadena de coincidencia actual se pasa como un parámetro , y variables como $ 1, $ 2, $ ', $ & y $ 'serán configuradas apropiadamente. El valor devuelto por el bloque será sustituido por la coincidencia en cada llamada. – rampion

+0

Derecha, voy a editar para aclararlo. –

Cuestiones relacionadas