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.

È stato utile?

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

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top