Je me demande comment puis-je obtenir quel modèle dans regex correspond.
J'ai cette regex (j'utilise .match dans Ruby):
(?i)(penalty is\W+[0-9]+\W+night)|(penalty of\W+[0-9]+\W+)
Maintenant, je sais comment renvoyer le texte correspondant dans une chaîne, mais existe-t-il un moyen d'obtenir une chaîne et un modèle correspondants pour cette chaîne? J'aurai donc deux résultats:
- Texte correspondant dans la chaîne: la pénalité est de 1 nuit
- Motif correspondant: (la pénalité est \ W + [0-9] + \ W + nuit)
Meilleures salutations.
3 réponses
pattern = /(?i)(penalty is\W+[0-9]+\W+night)|(penalty of\W+[0-9]+\W+)/
"penalty of 123 points".match(pattern)
=> #<MatchData "penalty of 123 " 1:nil 2:"penalty of 123 ">
Le nombre de capture non nul révèle quelle partie du modèle correspond. Il existe différentes manières de récupérer cette valeur, telles que:
"penalty of 123 points".match(pattern).captures
=> [nil, "penalty of 123 "]
# Get the index of the first *non-nil* element:
"penalty of 123 points".match(pattern).captures.find_index(&:itself)
=> 1
Ainsi, vous saurez si le premier ou le deuxième groupe correspond, selon que la chaîne de méthodes ci-dessus renvoie 0
ou 1
.
Si vous souhaitez rendre ce code un peu plus transparent (plus facile à comprendre comment il fonctionne), vous pouvez également envisager d'utiliser un groupe de capture nommé tel que:
pattern = /(?i)(?<night>penalty is\W+[0-9]+\W+night)|(?<other>penalty of\W+[0-9]+\W+)/
"penalty of 123 points".match(pattern)
=> #<MatchData "penalty of 123 " night:nil other:"penalty of 123 ">
"penalty of 123 points".match(pattern).named_captures
=> {"night"=>nil, "other"=>"penalty of 123 "}
"penalty of 123 points".match(pattern).named_captures.compact.keys.first
=> "other"
Pour aller plus loin, vous pouvez également définir chaque "sous-modèle" comme une expression régulière distincte pour référence future et les joindre pour le match principal, par exemple:
groups = {
"night" => /(?<night>penalty is\W+[0-9]+\W+night)/i,
"other" => /(?<other>penalty of\W+[0-9]+\W+)/i
]
pattern = Regexp.union(groups)
match_group_name = "penalty of 123 points".match(pattern).named_captures.compact.keys.first
puts "Pattern that matched: #{groups[match_group_name]}"
Autorisons n'importe quel nombre d'expressions régulières unies et concevons la méthode pour faciliter les tests.
Soit str
la chaîne et regexes
un tableau des expressions régulières. Pour l'exemple donné dans la question,
regexes = [/(?i)(?<night>penalty is\W+[0-9]+\W+night)/,
/(?i)(?<other>penalty of\W+[0-9]+\W+)/]
def doit(str, regexes)
regexes.each do |r|
m = str[r]
return [r, m] unless m.nil?
end
nil
end
REGEXPS = [
/(?<first>penalty is\W+[0-9]+\W+night)/i,
/(?<second>penalty of\W+[0-9]+\W+)/i
].freeze
Regexp.union(REGEXPS) =~ ""
$~.named_captures
Questions connexes
De nouvelles questions
ruby
Ruby est un langage interprété orienté objet dynamique et open source multi-plateforme. La balise [ruby] est destinée aux questions liées au langage Ruby, y compris sa syntaxe et ses bibliothèques. Les questions Ruby on Rails doivent être marquées avec [ruby-on-rails].