Scala expresiones regulares permiten opción Varias líneas
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.
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")