Ruby reemplaza la cadena con el patrón de expresiones regulares capturado

121

Tengo problemas para traducir esto a Ruby.

Aquí hay una pieza de JavaScript que hace exactamente lo que quiero hacer:

function get_code(str){
    return str.replace(/^(Z_.*): .*/,"$1")​​​​​​​​​​​​​​​​​​​​​​​​​​​;
}

He probado gsub , sub y replace, pero ninguno parece hacer lo que esperaba.

Aquí hay ejemplos de cosas que he probado:

"Z_sdsd: sdsd".gsub(/^(Z_.*): .*/) { |capture| capture }
"Z_sdsd: sdsd".gsub(/^(Z_.*): .*/, "$1")
"Z_sdsd: sdsd".gsub(/^(Z_.*): .*/, "#{$1}")
"Z_sdsd: sdsd".gsub(/^(Z_.*): .*/, "\1")
"Z_sdsd: sdsd".gsub(/(.).*/) { |capture| capture }
JD Isaacks
fuente
Debería mostrar el código real de lo que ha probado.
Ámbar
@Amber pongo muestra que he probado.
JD Isaacks

Respuestas:

192

Pruebe '\1'el reemplazo (las comillas simples son importantes, de lo contrario, debe escapar \):

"foo".gsub(/(o+)/, '\1\1\1')
#=> "foooooo"

Pero como solo parece estar interesado en el grupo de captura, tenga en cuenta que puede indexar una cadena con una expresión regular:

"foo"[/oo/]
#=> "oo"
"Z_123: foobar"[/^Z_.*(?=:)/]
#=> "Z_123"
Michael Kohl
fuente
68
Tenga en cuenta que esto solo funciona si la cadena de reemplazo está entre comillas simples . Perdí 5 minutos averiguando eso.
Vicky Chijwani
7
@MarkThomas: muchas veces probamos primero la respuesta superior / aceptada sin leer la totalidad de las respuestas. En general, ese parece ser el medio más eficaz de solucionar un problema. ¡Dale un descanso a Vicky! :)
Josh M.
@VickyChijwani Buen comentario, pero también tenga en cuenta que cuando se usa Ruby en línea (en la línea de comando con -e), es más probable que vea comillas dobles : printf "Punkinhead the name" | ruby -ne 'puts gsub /.*(the name)/, "Jonathans \\1"'porque la expresión proporcionada a -egeneralmente está entre comillas simples.
Jonathan Komar
¿Cómo hacer esto para todas las apariciones de patrón en la cadena?
Jagdeep Singh
1
@JagdeepSingh, de forma predeterminada, reemplaza todas las apariciones.
Iulian Onofrei
36

\1entre comillas dobles debe omitirse. Entonces tu quieres

"Z_sdsd: sdsd".gsub(/^(Z_.*): .*/, "\\1")

o

"Z_sdsd: sdsd".gsub(/^(Z_.*): .*/, '\1')

consulte los documentos en gsub donde dice "Si es una cadena entre comillas dobles, ambas referencias inversas deben ir precedidas de una barra diagonal inversa adicional".

Dicho esto, si solo desea el resultado del partido, puede hacer:

"Z_sdsd: sdsd".scan(/^Z_.*(?=:)/)

o

"Z_sdsd: sdsd"[/^Z_.*(?=:)/]

Tenga en cuenta que (?=:)es un grupo que no captura, por lo que :no aparece en su partido.

Mark Thomas
fuente
14
 "foobar".gsub(/(o+)/){|s|s+'ball'}
 #=> "fooballbar"
gaurav.singharoy
fuente
4
no sabía que podía hacer eso. ¡Agradable!
vreen
5

Si necesita usar una expresión regular para filtrar algunos resultados y ENTONCES usar solo el grupo de captura, puede hacer lo siguiente:

str = "Leesburg, Virginia  20176"
state_regex = Regexp.new(/,\s*([A-Za-z]{2,})\s*\d{5,}/)
# looks for the comma, possible whitespace, captures alpha,
# looks for possible whitespace, looks for zip

> str[state_regex]
=> ", Virginia  20176"

> str[state_regex, 1] # use the capture group
=> "Virginia"
gruñón
fuente
2
def get_code(str)
  str.sub(/^(Z_.*): .*/, '\1')
end
get_code('Z_foo: bar!') # => "Z_foo"
maerics
fuente
0

$ las variables solo se establecen para coincidir con el bloque:

"Z_sdsd: sdsd".gsub(/^(Z_.*): .*/) { "#{ $1.strip }" }

Esta es también la única forma de llamar a un método en la coincidencia. Esto no cambiará la coincidencia, solo strip"\ 1" (dejándolo sin cambios):

"Z_sdsd: sdsd".gsub(/^(Z_.*): .*/, "\\1".strip)
Lisapple
fuente