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 >).

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.


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


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]

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"

3

Un escaneo más simple sería:

String1.scan(/<(\S+)>/).last
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.