Ruby Language
Expressions régulières et opérations basées sur les regex
Recherche…
Groupes, nommés et autres.
Ruby étend la syntaxe de groupe standard (...)
avec un groupe nommé (?<name>...)
. Cela permet l'extraction par nom au lieu d'avoir à compter le nombre de groupes que vous avez.
name_reg = /h(i|ello), my name is (?<name>.*)/i #i means case insensitive
name_input = "Hi, my name is Zaphod Beeblebrox"
match_data = name_reg.match(name_input) #returns either a MatchData object or nil
match_data = name_input.match(name_reg) #works either way
if match_data.nil? #Always check for nil! Common error.
puts "No match"
else
match[0] #=> "Hi, my name is Zaphod Beeblebrox"
match[1] #=> "i" #the first group, (i|ello)
match[2] #=> "Zaphod Beeblebrox"
#Because it was a named group, we can get it by name
match[:name] #=> "Zaphod Beeblebrox"
match["name"] #=> "Zaphod Beeblebrox"
puts "Hello #{match[:name]}!"
end
L'index de la correspondance est compté en fonction de l'ordre des parenthèses de gauche (la totalité de l'expression rationnelle étant le premier groupe à l'index 0)
reg = /(((a)b)c)(d)/
match = reg.match 'abcd'
match[0] #=> "abcd"
match[1] #=> "abc"
match[2] #=> "ab"
match[3] #=> "a"
match[4] #=> "d"
= ~ opérateur
if /hay/ =~ 'haystack'
puts "There is hay in the word haystack"
end
Note: La commande est importante . Bien que la 'haystack' =~ /hay/
soit dans la plupart des cas équivalente, les effets secondaires peuvent différer:
- Les chaînes capturées à partir de groupes de capture nommés ne sont affectées à des variables locales que lorsque
Regexp#=~
est appelée (regexp =~ str
); - Le bon opérande pouvant être un objet arbitraire, pour
regexp =~ str
il sera appelé soitRegexp#=~
soitString#=~
.
Notez que cela ne renvoie pas une valeur true / false, mais renvoie soit l'index de la correspondance s'il est trouvé, soit nul s'il n'est pas trouvé. Parce que tous les entiers en ruby sont vrais (y compris 0) et nil est faux, cela fonctionne. Si vous voulez une valeur booléenne, utilisez #===
comme indiqué dans un autre exemple .
Quantificateurs
Quantifiers permet de spécifier le nombre de chaînes répétées.
Zéro ou un:
/a?/
Zéro ou beaucoup:
/a*/
Un ou plusieurs:
/a+/
Nombre exact:
/a{2,4}/ # Two, three or four /a{2,}/ # Two or more /a{,4}/ # Less than four (including zero)
Par défaut, les quantificateurs sont gourmands , ce qui signifie qu’ils prennent autant de caractères qu’ils le peuvent tout en effectuant une correspondance. Normalement, cela ne se remarque pas:
/(?<site>.*) Stack Exchange/ =~ 'Motor Vehicle Maintenance & Repair Stack Exchange'
Le site
groupe de capture nommé sera défini sur "Maintenance et réparation des véhicules automobiles" comme prévu. Mais si «Stack Exchange» est une partie facultative de la chaîne (car il pourrait s'agir de «Stack Overflow» à la place), la solution naïve ne fonctionnera pas comme prévu:
/(?<site>.*)( Stack Exchange)?/
Cette version correspondra toujours, mais la capture nommée inclura "Stack Exchange" puisque *
mange avidement ces caractères. La solution consiste à ajouter un autre point d'interrogation pour rendre le *
paresseux:
/(?<site>.*?)( Stack Exchange)?/
Ajout ?
à tout quantificateur le rendra paresseux.
Classes de caractères
Décrit les plages de symboles
Vous pouvez énumérer explicitement les symboles
/[abc]/ # 'a' or 'b' or 'c'
Ou utiliser des gammes
/[a-z]/ # from 'a' to 'z'
Il est possible de combiner des plages et des symboles simples
/[a-cz]/ # 'a' or 'b' or 'c' or 'z'
Le trait d'union ( -
) est traité comme charachter
/[-a-c]/ # '-' or 'a' or 'b' or 'c'
Les classes peuvent être négatives lorsque des symboles précèdent avec ^
/[^a-c]/ # Not 'a', 'b' or 'c'
Il existe des raccourcis pour les classes répandues et les charachters spéciaux, ainsi que des fins de ligne
^ # Start of line
$ # End of line
\A # Start of string
\Z # End of string, excluding any new line at the end of string
\z # End of string
. # Any single character
\s # Any whitespace character
\S # Any non-whitespace character
\d # Any digit
\D # Any non-digit
\w # Any word character (letter, number, underscore)
\W # Any non-word character
\b # Any word boundary
\n
se comprendra simplement comme nouvelle ligne
Pour échapper à n'importe quel charachter réservé, tel que /
ou []
et d'autres, utilisez une barre oblique inverse (barre oblique à gauche)
\\ # => \
\[\] # => []
Expressions régulières dans les déclarations de cas
Vous pouvez tester si une chaîne correspond à plusieurs expressions régulières à l'aide d'une instruction switch.
Exemple
case "Ruby is #1!"
when /\APython/
puts "Boooo."
when /\ARuby/
puts "You are right."
else
puts "Sorry, I didn't understand that."
end
Cela fonctionne parce que les instructions de cas sont vérifiées pour l'égalité en utilisant l'opérateur ===
, pas l'opérateur ==
. Quand une regex est sur le côté gauche d'une comparaison utilisant ===
, elle testera une chaîne pour voir si elle correspond.
Définir une expression rationnelle
Une expression régulière peut être créée de trois manières différentes dans Ruby.
en utilisant des barres obliques:
/ /
en utilisant
%r{}
en utilisant
Regex.new
#The following forms are equivalent regexp_slash = /hello/ regexp_bracket = %r{hello} regexp_new = Regexp.new('hello') string_to_match = "hello world!" #All of these will return a truthy value string_to_match =~ regexp_slash # => 0 string_to_match =~ regexp_bracket # => 0 string_to_match =~ regexp_new # => 0
rencontre? - Résultat booléen
Retourne true
ou false
, qui indique si l'expression rationnelle est mise en correspondance ou non sans mettre $~
jour $~
et d'autres variables associées. Si le second paramètre est présent, il spécifie la position dans la chaîne pour commencer la recherche.
/R.../.match?("Ruby") #=> true
/R.../.match?("Ruby", 1) #=> false
/P.../.match?("Ruby") #=> false
Ruby 2.4+
Utilisation rapide commune
Les expressions régulières sont souvent utilisées dans les méthodes en tant que paramètres pour vérifier si d'autres chaînes sont présentes ou pour rechercher et / ou remplacer des chaînes.
Vous verrez souvent ce qui suit:
string = "My not so long string"
string[/so/] # gives so
string[/present/] # gives nil
string[/present/].nil? # gives true
Donc, vous pouvez simplement l'utiliser comme une vérification si une chaîne contient une sous-chaîne
puts "found" if string[/so/]
Plus avancé mais toujours court et rapide: recherchez un groupe spécifique en utilisant le deuxième paramètre, 2 est le second dans cet exemple car la numérotation commence à 1 et non à 0, un groupe est ce qui est entre parenthèses.
string[/(n.t).+(l.ng)/, 2] # gives long
Aussi souvent utilisé: rechercher et remplacer par sub
ou gsub
, \1
donne le premier groupe trouvé, \2
le second:
string.gsub(/(n.t).+(l.ng)/, '\1 very \2') # My not very long string
Le dernier résultat est mémorisé et peut être utilisé sur les lignes suivantes
$2 # gives long