2009-07-06 14 views
20

Estoy aprendiendo Scala, así que esto es probablemente bastante noob-irific.Scala Regex enable Opción Multiline

Quiero tener una expresión regular multilínea.

en Ruby sería:

MY_REGEX = /com:Node/m 

Mi Scala se parece a:

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

Aquí es mi función de correspondencia:

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

Y lo estoy llamando de este modo:

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

que he probado:

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

Y realmente me gustaría evitar tener que utilizar java.util.regex.Pattern. Cualquier consejo muy apreciado.

+0

¡salud para formatear! no funcionó para mí –

+1

Debe dejar una línea en blanco encima y debajo de cada bloque de código. –

Respuesta

36

Este es un problema muy común cuando se usa por primera vez Scala Regex.

Cuando utiliza la coincidencia de patrones en Scala, intenta hacer coincidir toda la cadena, como si estuviera usando "^" y "$" (y no activó el análisis multilínea, que coincide \ n con^y $)

La manera de hacer lo que quiera 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 
    } 

que encontraría encontrar la primera instancia de scriptNode dentro de valor, y volver que ejemplo como v (si desea que el cadena completa, solo imprimir valor). 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 
    } 

Que imprimiría todo el valor. En este ejemplo, (?) Activa la coincidencia de puntos (es decir, haciendo coincidir "." Con líneas nuevas), y. * Antes y después del patrón buscado 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 
    } 
+1

cosas encantadoras. ¡Aclamaciones! –

+21

Puede que no sea claro para los lectores descremados como yo, pero la inclusión de '(? S)' es clave aquí en lo que respecta a la coincidencia contra cadenas de varias líneas. Ver http://download.oracle.com/javase/1.4.2/docs/api/java/util/regex/Pattern.html#DOTALL – Synesso

+4

@Synesso su enlace está roto ahora. aquí está el java 7 equivalente http://docs.oracle.com/javase/7/docs/api/java/util/regex/Pattern.html#DOTALL – harschware

5

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 el aire Scala único.

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

3

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

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