2011-11-28 12 views
28

Con bastante frecuencia comparo las cadenas con expresiones regulares. En Java:..Coincidencia con una expresión regular en Scala

java.util.regex.Pattern.compile ("\ w +") ("matcher this_is") coincide con

Ay. Scala tiene muchas alternativas.

  1. "\\w+".r.pattern.matcher("this_is").matches
  2. "this_is".matches("\\w+")
  3. "\\w+".r unapplySeq "this_is" isDefined
  4. val R = "\\w+".r; "this_is" match { case R() => true; case _ => false}

La primera es igual de peso pesado como el código de Java.

El problema con el segundo es que no puede suministrar un patrón compilado ("this_is".matches("\\w+".r")). (Esto parece ser un anti-patrón ya que casi cada vez que hay un método que toma una expresión regular para compilar hay una sobrecarga que toma una expresión regular).

El problema con el tercero es que abusa de unapplySeq y por lo tanto es críptico.

El cuarto es genial cuando se descomponen partes de una expresión regular, pero es demasiado pesado cuando solo quieres un resultado booleano.

¿Me está faltando una manera fácil de buscar coincidencias con una expresión regular? ¿Hay alguna razón por la cual String#matches(regex: Regex): Boolean no está definido? De hecho, ¿dónde se define String#matches(uncompiled: String): Boolean?

+3

Vale la pena señalar que 'String # matches (string: String)' no está definido por la especificación 2.9 o [StringLike] (http://www.scala-lang.org/api/current/index.html # scala.collection.immutable.StringLike) escriba de la biblioteca estándar. Es, de hecho, un artefacto de la definición de [Strings in Java] (http://docs.oracle.com/javase/6/docs/api/java/lang/String.html#matches (java.lang. Cuerda)). – ig0774

+0

No entiendo lo que quiere decir con demasiado pesado en el primer ejemplo? ¿Quiere decir que el código es demasiado largo, o quiere decir que está haciendo demasiado trabajo? –

+1

código demasiado, el trabajo es exactamente lo que quiero – schmmd

Respuesta

31

puede definir un patrón de esta manera:

scala> val Email = """(\w+)@([\w\.]+)""".r 

findFirstIn volverá Some[String] si coincide o bien None.

scala> Email.findFirstIn("[email protected]") 
res1: Option[String] = Some([email protected]) 

scala> Email.findFirstIn("test") 
rest2: Option[String] = None 

Incluso se puede extraer:

scala> val Email(name, domain) = "[email protected]" 
name: String = test 
domain: String = example.com 

Por último, también se puede utilizar el método convencional String.matches (e incluso reciclar el definido previamente Email Regexp:.

scala> "[email protected]".matches(Email.toString) 
res6: Boolean = true 

la esperanza que esto ayudará

+0

Sí, supongo que podría hacer '" ""^(\ w +) $ "" ". FindFirstIn (" test_string ")' ... – schmmd

+1

@schmmd No te olvides de '.r' para compilar' Regex'. – David

+0

¡Uy! ¿No sería bueno tener 'matches' definidos en' Regex'? – schmmd

12

Creé un pequeño patrón "Pimp my Library" para ese problema Tal vez te ayude.

import util.matching.Regex 

object RegexUtils { 
    class RichRegex(self: Regex) { 
    def =~(s: String) = self.pattern.matcher(s).matches 
    } 
    implicit def regexToRichRegex(r: Regex) = new RichRegex(r) 
} 

Ejemplo de uso

scala> import RegexUtils._ 
scala> """\w+""".r =~ "foo" 
res12: Boolean = true 
+1

¡Genial! Aunque llamaría al operador '~' en lugar de '~ =' porque los operadores que terminan en '=' me parecen mutaciones in situ (de las convenciones de C++ y Python ...). –

+0

Sí, apunte a Perl's = ~ pero tengo el nombre al revés, al parecer. –

+0

Solo pensé que mencionaría que Haskell tiene un operador = ~ para corresponder expresiones regulares también. He visto que '~ =' solía significar no iguales, como '! ='. – eriksensei

3

normalmente utilizo

val regex = "...".r 
if (regex.findFirstIn(text).isDefined) ... 

pero creo que es bastante incómodo.

Cuestiones relacionadas