Extraiga una subcadena de una cadena en Ruby utilizando una expresión regular

130

¿Cómo puedo extraer una subcadena de una cadena en Ruby?

Ejemplo:

String1 = "<name> <substring>"

Quiero extraer substringde String1(es decir, todo dentro de la última aparición de <y >).

Madhusudhan
fuente

Respuestas:

134
String1.scan(/<([^>]*)>/).last.first

scancrea una matriz que, para cada <item>en String1contiene el texto entre el <y el >en una matriz de una elemento (porque cuando se utiliza con una expresión regular que contiene grupos de captura, exploración crea una matriz que contiene las capturas para cada partido). lastle da la última de esas matrices y firstluego le da la cadena que contiene.

sepp2k
fuente
319
"<name> <substring>"[/.*<([^>]*)/,1]
=> "substring"

No es necesario usar scan, si solo necesitamos un resultado.
No es necesario usar Python match, cuando tenemos Ruby String[regexp,#].

Ver: http://ruby-doc.org/core/String.html#method-i-5B-5D

Nota: str[regexp, capture] → new_str or nil

Nakilon
fuente
37
No es necesario desacreditar otras soluciones perfectamente válidas (y podría opinar, más legibles).
coreyward
41
@coreyward, si son mejores, por favor, discuta. Por ejemplo, la solución de sepp2k es más flexible, y es por eso que señalé if we need only one resultmi solución. Y match()[]es más lento, porque son dos métodos en lugar de uno.
Nakilon el
44
Este es el más rápido de todos los métodos presentados, pero incluso el método más lento toma solo 4.5 microsegundos en mi máquina. No me importa especular por qué este método es más rápido. En rendimiento, la especulación es inútil . Solo la medición cuenta.
Wayne Conrad el
8
Encuentro esta solución más sencilla y directa (ya que soy nuevo en Ruby). Gracias.
Ryan H.
La legibilidad de @Nakilon puede superar las pequeñas diferencias de rendimiento al considerar el éxito general de un producto y equipo, por lo que Coreyward hizo un comentario válido. Dicho esto, creo que string[regex]puede ser tan legible en este escenario, así que eso es lo que usé personalmente.
Nick
24

Puedes usar una expresión regular para eso con bastante facilidad ...

Permitir espacios alrededor de la palabra (pero no mantenerlos):

str.match(/< ?([^>]+) ?>\Z/)[1]

O sin los espacios permitidos:

str.match(/<([^>]+)>\Z/)[1]
coreyward
fuente
1
No estoy seguro de que lo último <>realmente deba ser lo último en la cadena. Si, por ejemplo, la cadena foo <bar> bazestá permitida (y se supone que da el resultado bar), esto no funcionará.
sepp2k
Acabo de basarme en la cadena de muestra que proporcionó.
coreyward
10

Aquí hay un enfoque un poco más flexible usando el matchmétodo. Con esto, puede extraer más de una cadena:

s = "<ants> <pants>"
matchdata = s.match(/<([^>]*)> <([^>]*)>/)

# Use 'captures' to get an array of the captures
matchdata.captures   # ["ants","pants"]

# Or use raw indices
matchdata[0]   # whole regex match: "<ants> <pants>"
matchdata[1]   # first capture: "ants"
matchdata[2]   # second capture: "pants"
Grant Birchmeier
fuente
3

Un escaneo más simple sería:

String1.scan(/<(\S+)>/).last
Navid
fuente