2009-02-06 28 views
75

Estoy buscando una forma de realizar una coincidencia de expresiones regulares en una cadena en Ruby y tener un cortocircuito en la primera coincidencia.Devolver la primera coincidencia de Ruby regex

La cadena que estoy procesando es larga y, por lo que parece, la forma estándar (método match) procesará todo, recopilará cada coincidencia y devolverá un objeto MatchData que contenga todas las coincidencias.

match = string.match(/regex/)[0].to_s 

Respuesta

106

Puede probar variableName[/regular expression/]. Este es un ejemplo del resultado de IRB:

irb(main):003:0> names = "erik kalle johan anders erik kalle johan anders" 
=> "erik kalle johan anders erik kalle johan anders" 
irb(main):004:0> names[/kalle/] 
=> "kalle" 
+0

¿Esto no está haciendo una coincidencia y devuelve el primer resultado detrás de escena? – Gishu

+5

Después de algunos benchmarking con varias cadenas de longitud y mirando la fuente C, Regex.match hace cortocircuitos y solo encuentra la primera coincidencia. –

+2

Limpio, no sabía acerca de este atajo. – Pierre

19

Si al menos una existencia de un partido es importante, se puede ir con

/regexp/ =~ "string" 

De cualquier manera, match sólo debe devolver el primer golpe, mientras que scan búsquedas a lo largo de toda la cadena. Por lo tanto, si

matchData = "string string".match(/string/) 
matchData[0] # => "string" 
matchData[1] # => nil - it's the first capture group not a second match 
1

Una expresión regular (regex) no es más que una máquina de estados finitos (FSM).

Un FSM intenta responder la pregunta "¿Es posible o no este estado?"

Sigue intentando hacer coincidir un patrón hasta que se encuentra una coincidencia (éxito) o hasta que se exploren todas las rutas y no se haya encontrado ninguna coincidencia (error).

En caso de éxito, la pregunta "¿Es posible o no este estado?" ha sido respondido con un "sí". Por lo tanto, no es necesario hacer más coincidencias y la expresión regular regresa.

Consulte this y this para obtener más información al respecto.

Además: here is an interesting example para demostrar cómo funciona la expresión regular. Aquí, una expresión regular se usa para detectar si un número de entrega es primo. Este ejemplo está en perl, pero también puede escribirse en ruby.

44

Puede utilizar []: (que es como match)

"[email protected]"[/\+([^@]+)/, 1] # matches what is inside() 
# => "account2" 
"[email protected]"[/\+([^@]+)/, 0] # matches whole regexp 
# => "+account2" 
+3

mejor respuesta completa – akostadinov

1

todavía no estoy seguro de si esta característica es impresionante o simplemente totalmente loco, pero su expresión regular puede definir variables locales.

/\$(?<dollars>\d+)\.(?<cents>\d+)/ =~ "$3.67" #=> 0 
dollars #=> "3" 

(Tomado de http://ruby-doc.org/core-2.1.1/Regexp.html).

Cuestiones relacionadas