Je ne suis pas sûr de bien comprendre comment fonctionnent les groupes sans capture. Je cherche une regex pour produire ce résultat: 5.214
. Je pensais que la regex ci-dessous fonctionnerait, mais elle remplace tout, y compris les groupes non capturés. Comment puis-je écrire une expression rationnelle pour ne remplacer que les groupes de capture?
"5,214".gsub(/(?:\d)(,)(?:\d)/, '.')
# => ".14"
Mon résultat souhaité:
"5,214".gsub(some_regex)
#=> "5.214
Tu ne peux pas. gsub
remplace la correspondance entière; il ne fait rien avec les groupes capturés. Que les groupes soient capturés ou non ne fera aucune différence.
Pour obtenir ce résultat, vous devez utiliser lookbehind et lookahead.
"5,214".gsub(/(?<=\d),(?=\d)/, '.')
les groupes non capturés consomment toujours la correspondance
utilisation"5,214".gsub(/(\d+)(,)(\d+)/, '\1.\3')
ou"5,214".gsub(/(?<=\d+)(,)(?=\d+)/, '.')
gsub
remplace l'intégralité de la correspondance produite par le moteur d'expressions régulières.
RTFM , les deux constructions de groupe capturant/non capturant ne sont pas conservées. Cependant, vous pouvez utiliser lookaround assertions qui ne "consomme" aucun caractère de la chaîne.
"5,214".gsub(/\d\K,(?=\d)/, '.')
Explication: La séquence d'échappement \K
réinitialise le point de départ de la correspondance signalée et les caractères précédemment consommés ne sont plus inclus}. Cela étant dit, nous cherchons et correspondons à la virgule, et le témoin positif indique qu'un chiffre suit.
Il est également possible d'utiliser Regexp.last_match
(également disponible via $~
) dans la version en bloc pour accéder à la totalité de la MatchData
:
"5,214".gsub(/(\d),(\d)/) { |_|
match = Regexp.last_match
"#{match[1]}.#{match[2]}"
}
Cela évolue mieux vers des cas d'utilisation plus impliqués.
Nota bene, de la documentation Ruby:
the :: last_match est local pour le thread et la portée de la méthode qui a fait correspondre le modèle.
Je ne connais rien à Ruby.
Mais de ce que je vois dans le tutoriel
gsub signifie replace, le motif doit être /(?<=\d+),(?=\d+)/
, remplacez simplement la virgule par le point ou utilisez capture /(\d+),(\d+)/
et remplacez la chaîne par "\1.\2"
?
Vous n'avez pas besoin d'expressions rationnelles pour obtenir ce dont vous avez besoin:
'1,200.00'.tr('.','!').tr(',','.').tr('!', ',')
1,200!00
)1.200!00
)1.200,00
)