web-dev-qa-db-fra.com

Groupe de capture Scala utilisant regex

Disons que j'ai ce code:

val string = "one493two483three"
val pattern = """two(\d+)three""".r
pattern.findAllIn(string).foreach(println)

Je m'attendais à ce que findAllIn ne retourne que 483, mais il a plutôt renvoyé two483three. Je sais que je pourrais utiliser unapply pour extraire uniquement cette partie, mais je devrais avoir un motif pour toute la chaîne, quelque chose comme:

 val pattern = """one.*two(\d+)three""".r
 val pattern(aMatch) = string
 println(aMatch) // prints 483

Y a-t-il un autre moyen d'y parvenir sans utiliser les classes de Java.util directement et sans utiliser inapply? 

58
Geo

Voici un exemple de la façon dont vous pouvez accéder à group(1) de chaque correspondance:

val string = "one493two483three"
val pattern = """two(\d+)three""".r
pattern.findAllIn(string).matchData foreach {
   m => println(m.group(1))
}

Ceci imprime "483" ( comme on le voit sur ideone.com ).


L'option lookaround

En fonction de la complexité du modèle, vous pouvez également utiliser des comparaisons pour que uniquement corresponde à la partie souhaitée. Ça va ressembler à quelque chose comme ça: 

val string = "one493two483three"
val pattern = """(?<=two)\d+(?=three)""".r
pattern.findAllIn(string).foreach(println)

Ce qui précède imprime également "483" ( comme indiqué sur ideone.com ).

Références

87
polygenelubricants
val string = "one493two483three"
val pattern = """.*two(\d+)three.*""".r

string match {
  case pattern(a483) => println(a483) //matched group(1) assigned to variable a483
  case _ => // no match
}
27
caiiiycuk

Vous voulez regarder group(1), vous êtes en train de regarder group(0), qui est "la chaîne complète correspondante".

Voir ce tutoriel sur les expressions rationnelles .

13
Stephen

En démarrant Scala 2.13, en guise d'alternative aux solutions d'expression rationnelle, il est également possible de faire correspondre un motif à un String by sans appliquer d'interpolateur de chaîne :

"one493two483three" match { case s"${x}two${y}three" => y }
// String = "483"

Ou même:

val s"${x}two${y}three" = "one493two483three"
// x: String = one493
// y: String = 483

Si vous attendez une entrée ne correspondant pas, vous pouvez ajouter un garde de modèle par défaut:

"one493deux483three" match {
  case s"${x}two${y}three" => y
  case _                   => "no match"
}
// String = "no match"
1
Xavier Guihot
def extractFileNameFromHttpFilePathExpression(expr: String) = {
//define regex
val regex = "http4.*\\/(\\w+.(xlsx|xls|Zip))$".r
// findFirstMatchIn/findAllMatchIn returns Option[Match] and Match has methods to access capture groups.
regex.findFirstMatchIn(expr) match {
  case Some(i) => i.group(1)
  case None => "regex_error"
}
}
extractFileNameFromHttpFilePathExpression(
    "http4://testing.bbmkl.com/document/sth1234.Zip")
1
Gaurav Khare