Scala Regex abilitare l'opzione multilinea
Domanda
Sto imparando Scala, quindi questo è probabilmente abbastanza noob-irific.
Voglio avere un'espressione regolare multilinea.
In Ruby sarebbe:
MY_REGEX = /com:Node/m
Il mio Scala si presenta come:
val ScriptNode = new Regex("""<com:Node>""")
Ecco la mia funzione match:
def matchNode( value : String ) : Boolean = value match
{
case ScriptNode() => System.out.println( "found" + value ); true
case _ => System.out.println("not found: " + value ) ; false
}
E sto chiamando in questo modo:
matchNode( "<root>\n<com:Node>\n</root>" ) // doesn't work
matchNode( "<com:Node>" ) // works
Ho provato:
val ScriptNode = new Regex("""<com:Node>?m""")
E mi piacerebbe davvero evitare di dover utilizzare java.util.regex.Pattern. Eventuali suggerimenti molto apprezzato.
Soluzione
Questo è un problema molto comune al primo utilizzo Scala Regex.
Quando si utilizza il pattern matching a Scala, si cerca di far corrispondere l'intera stringa, come se si stesse utilizzando "^" e "$" (e non attivare l'analisi multi-linea, che corrisponde \ n per ^ e $) .
Il modo per fare quello che vuoi sarebbe uno dei seguenti:
def matchNode( value : String ) : Boolean =
(ScriptNode findFirstIn value) match {
case Some(v) => println( "found" + v ); true
case None => println("not found: " + value ) ; false
}
che troverebbe trovare la prima istanza di scriptNode all'interno valore e tornare che esempio come v (se si desidera che l'intera stringa, solo il valore di stampa). Oppure:
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
}
Il che stampare tutto ogni valore. In questo esempio, (? S) attiva corrispondente dotall (cioè corrispondenti "" per nuove linee), e il. * Prima e dopo il modello ricercati assicura che corrisponderà qualsiasi stringa. Se si voleva "v", come nel primo esempio, si potrebbe fare questo:
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
}
Altri suggerimenti
Solo un addendum veloce e sporco: il metodo .r
su RichString
converte tutte le stringhe di scala.util.matching.Regex
, in modo da poter fare qualcosa di simile:
"""(?s)a.*b""".r replaceAllIn ( "a\nb\nc\n", "A\nB" )
E che tornerà
A
B
c
Io uso questo tutto il tempo per regex-scripting veloce e sporco nella console scala.
O in questo 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
}
}
Solo il mio tentativo di ridurre l'uso della parola new
nel codice in tutto il mondo. ;)
Solo una piccola aggiunta, l'uso cercato di utilizzare il (?m)
(multilinea) bandiera (anche se potrebbe non essere adatto qui), ma qui è il modo giusto per usarlo:
es. invece di
val ScriptNode = new Regex("""<com:Node>?m""")
utilizzo
val ScriptNode = new Regex("""(?m)<com:Node>""")
Ma ancora una volta il (? S) bandiera è più adatto a questa domanda (l'aggiunta di questa risposta solo perché il titolo è "Scala Regex abilitare l'opzione Multiriga")