2009-07-06 15 views
20

Ich lerne Scala, also ist das wahrscheinlich ziemlich noob-irisch.Scala Regex aktivieren Multiline Option

Ich möchte einen mehrzeiligen regulären Ausdruck haben.

In Ruby wäre es:

MY_REGEX = /com:Node/m 

Meine Scala wie folgt aussieht:

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

Hier Funktion mein Spiel ist:

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

Und ich bin es, wie so nennen:

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

Ich habe versucht:

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

Und ich würde wirklich java.util.regex.Pattern verwenden, um vermeiden möchten. Irgendwelche Tipps sehr geschätzt.

+0

Prost für die Formatierung! funktionierte nicht für mich –

+1

Sie müssen eine leere Zeile über und unter jedem Codeblock lassen. –

Antwort

36

Dies ist ein sehr häufiges Problem bei der ersten Verwendung von Scala Regex.

Wenn Sie Mustervergleich in Scala verwenden, versucht es die gesamte Zeichenfolge zu vergleichen, als ob Sie "^" und "$" verwenden würden (und aktiviert Multi-Line-Parsing nicht, die \ n zu^und $ entspricht).

Die Art und Weise zu tun, was Sie eine der folgenden Möglichkeiten würden wollen:

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

, die die erste Instanz von scriptNode innerhalb Wert finden finden würde, und zurück dass Instanz als v (wenn Sie möchten, ganze Zeichenfolge, nur Druckwert). Oder andersherum:

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 
    } 

Welches würde alle Wert drucken. In diesem Beispiel aktiviert (? S) das Punktabgleich-Matching (dh das Anpassen von "." An neue Zeilen), und das. * Vor und nach dem gesuchten Muster stellt sicher, dass es mit einer beliebigen Zeichenfolge übereinstimmt. Wenn Sie „v“ wie im ersten Beispiel wollen, könnten Sie dies tun:

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

Schöne Sachen. Prost! –

+21

Es ist vielleicht nicht klar, Skim-Leser wie ich selbst, aber die Einbeziehung von '(? S)' ist der Schlüssel hier in Bezug auf die Anpassung an Multi-Line-Strings. Siehe http://download.oracle.com/javase/1.4.2/docs/api/java/util/regex/Pattern.html#DOTALL – Synesso

+4

@Synesso, Ihr Link ist jetzt unterbrochen. Hier ist das Java 7 Äquivalent http://docs.oracle.com/javase/7/docs/api/java/util/regex/Pattern.html#DOTALL – harschware

5

Nur ein schnellen und schmutzigen Nachtrag: die .r Methode auf RichString alle Strings zu scala.util.matching.Regex konvertiert, so können Sie etwas tun:

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

und das wird wieder

A 
B 
c 

ich benutze diese die ganze Zeit für quick and dirty regex-Scripting in der scala con Sohle, einzig, alleinig.

Oder in diesem Fall:

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 
    } 
} 

Nur mein Versuch, die Verwendung des Wortes new in Code weltweit zu reduzieren.;)

3

Nur ein kleiner Zusatz, verwenden Sie die (?m) (mehrzeilige) Flagge zu verwenden versucht, (obwohl es nicht geeignet hier sein könnte), aber hier ist der richtige Weg, es zu benutzen:

z.B. statt

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

Verwendung

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

Aber auch hier die (? s) Flagge ist besser geeignet in dieser Frage (das Hinzufügen dieser Antwort nur, weil der Titel "Scala Regex ermöglicht mehrzeilige Option" ist)