Pregunta

Estoy aprendiendo Scala, así que esto es probablemente bastante noob-irific.

Quiero tener una expresión regular de varias líneas.

En Rubí sería:

MY_REGEX = /com:Node/m

Mi Scala se ve así:

val ScriptNode =  new Regex("""<com:Node>""")

Esta es mi función de comparación:

def matchNode( value : String ) : Boolean = value match 
{
    case ScriptNode() => System.out.println( "found" + value ); true
    case _ => System.out.println("not found: " + value ) ; false
}

Y yo estoy llamando de esta manera:

matchNode( "<root>\n<com:Node>\n</root>" ) // doesn't work
matchNode( "<com:Node>" ) // works

He intentado:

val ScriptNode =  new Regex("""<com:Node>?m""")

Y me gusta mucho para no tener que utilizar java.util.regex.Pattern. Cualquier consejo muy apreciados.

¿Fue útil?

Solución

Este es un problema muy común cuando primero usando Scala expresión regular.

Cuando se utiliza la coincidencia de patrones en Scala, intenta hacer coincidir la cadena entera, como si estuviera usando "^" y "$" (y no activó el análisis de varias líneas, que coincide con \ n a ^ y $) .

La manera de hacer lo que quieres que sería uno de los siguientes:

def matchNode( value : String ) : Boolean = 
  (ScriptNode findFirstIn value) match {    
    case Some(v) => println( "found" + v ); true    
    case None => println("not found: " + value ) ; false
  }

¿Qué encontraría encontrar la primera instancia de scriptNode dentro de valor, y volver que ejemplo, como v (si desea que toda la cadena, justo valor de impresión). O bien:

val ScriptNode =  new Regex("""(?s).*<com:Node>.*""")
def matchNode( value : String ) : Boolean = 
  value match {    
    case ScriptNode() => println( "found" + value ); true    
    case _ => println("not found: " + value ) ; false
  }

Lo que imprimiría todo todo valor. En este ejemplo, (? S) activa coincidente dotall (es decir, a juego "" a las nuevas líneas), y el. * Antes y después de que el patrón buscadas asegura que coincidirá con cualquier cadena. Si quería "v", como en el primer ejemplo, se puede hacer esto:

val ScriptNode =  new Regex("""(?s).*(<com:Node>).*""")
def matchNode( value : String ) : Boolean = 
  value match {    
    case ScriptNode(v) => println( "found" + v ); true    
    case _ => println("not found: " + value ) ; false
  }

Otros consejos

Sólo una adición rápida y sucia: el método .r en RichString convierte todas las cadenas a scala.util.matching.Regex, por lo que puede hacer algo como esto:

"""(?s)a.*b""".r replaceAllIn ( "a\nb\nc\n", "A\nB" )

Y eso va a volver

A
B
c

Yo uso esta todo el tiempo para expresiones regulares de scripts rápida y sucia en la consola Scala.

O en este caso:

def matchNode( value : String ) : Boolean = {

    """(?s).*(<com:Node>).*""".r.findAllIn( text ) match {

       case ScriptNode(v) => System.out.println( "found" + v ); true    

       case _ => System.out.println("not found: " + value ) ; false
    }
}

Sólo mi intento de reducir el uso de la palabra en código new en todo el mundo. ;)

Sólo una pequeña adición, el uso trató de usar la (?m) (Varias líneas) bandera (aunque podría no ser adecuado aquí) pero aquí es la forma correcta de utilizarlo:

por ejemplo. en lugar de

val ScriptNode =  new Regex("""<com:Node>?m""")

uso

val ScriptNode =  new Regex("""(?m)<com:Node>""")

Pero de nuevo el (? S) bandera es más adecuada en esta pregunta (la adición de esta respuesta sólo porque el título es "Scala expresiones regulares permiten opción Varias líneas")

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top