Scala Regex activer l'option multiligne
Question
J'apprends Scala, il est sans doute assez Noob-irific.
Je veux 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>""")
Voici ma fonction de correspondance:
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. Des conseils très appréciés.
La solution
Ceci est un problème très fréquent lors de la première utilisation de Scala Regex.
Lorsque vous utilisez pattern matching dans Scala, il tente de faire correspondre la chaîne entière, comme si vous utilisiez « ^ » et « $ » (et ne pas activer l'analyse de plusieurs lignes, ce 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 dans la valeur et retour que par exemple que v (si vous voulez que la 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
}
Ce qui imprimerait toute valeur tout. Dans cet exemple, (? S) active correspondant dotall (c.-à-correspondant « » aux nouvelles lignes), et le. * Avant et après le modèle cherchés assure qu'il ne 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
}
Autres conseils
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 la console scala.
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. ;)
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 »)