2009-07-06 7 views
20

J'apprends Scala, donc c'est probablement assez cool.Scala Regex active l'option Multiline

Je souhaite avoir une expression régulière multiligne.

Dans Ruby, il serait:

MY_REGEX = /com:Node/m 

Mon Scala ressemble:

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

Voilà ma fonction de match:

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

Et je vous appelle comme ceci:

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

J'ai essayé:

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

Et je voudrais vraiment éviter d'avoir à utiliser java.util.regex.Pattern. Tous les conseils grandement appréciés.

+0

Bravo pour le formatage! n'a pas fonctionné pour moi –

+1

Vous devez laisser une ligne vide au-dessus et en dessous de chaque bloc de code. –

Répondre

36

Il s'agit d'un problème très courant lors de la première utilisation de Scala Regex. Lorsque vous utilisez la correspondance de modèle dans Scala, il essaie de faire correspondre la chaîne entière, comme si vous utilisiez "^" et "$" (et n'a pas activé l'analyse multi-ligne, qui correspond à \ n à^et $).

La façon de faire ce que vous voulez serait l'un des éléments suivants:

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

qui trouverait trouver la première instance de scriptNode intérieur valeur, et le retour que exemple que v (si vous voulez chaîne entière, juste valeur d'impression). Ou 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 
    } 

Qui imprimerait toute la valeur. Dans cet exemple, (? S) active la correspondance point-à-point (c.-à-d., Assortir "." Aux nouvelles lignes), et le. * Avant et après le motif recherché assure qu'il correspondra à n'importe quelle chaîne. Si vous vouliez « v » comme dans le premier exemple, vous pouvez faire ceci:

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

Belle affaire. À votre santé! –

+21

Cela peut ne pas être clair pour les lecteurs de skim comme moi, mais l'inclusion de '(? S)' est la clé ici en ce qui concerne la comparaison avec les chaînes multi-lignes. Voir http://download.oracle.com/javase/1.4.2/docs/api/java/util/regex/Pattern.html#DOTALL – Synesso

+4

@Synesso votre lien est rompu maintenant. voici l'équivalent java 7 http://docs.oracle.com/javase/7/docs/api/java/util/regex/Pattern.html#DOTALL – harschware

5

Juste un addendum rapide et sale: la méthode .r sur RichString convertit toutes les chaînes de scala.util.matching.Regex, de sorte que vous pouvez faire quelque chose comme ceci:

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

et qui renverra

A 
B 
c 

Je l'utilise tout le temps pour regex-script rapide et sale dans le scala con Unique.

Ou dans ce cas:

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

Juste ma tentative de réduire l'utilisation du mot new dans le code dans le monde entier.;)

3

Juste un petit plus, l'utilisation a essayé d'utiliser la (?m) (multiline) (bien qu'il pourrait ne pas convenir ici) mais voici la bonne façon de l'utiliser:

par exemple au lieu de

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

utilisation

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

Mais encore une fois le (? s) drapeau est plus approprié dans cette question (l'ajout de cette réponse que parce que le titre est "Scala Regex activer l'option multiligne")