web-dev-qa-db-fra.com

Ruby regex - groupe capturé uniquement par gsub

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
15
diasks2

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)/, '.')
19
sawa

les groupes non capturés consomment toujours la correspondance
utilisation
"5,214".gsub(/(\d+)(,)(\d+)/, '\1.\3')
ou
"5,214".gsub(/(?<=\d+)(,)(?=\d+)/, '.')

9
alpha bravo

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.

7
hwnd

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.

3
Raphael

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"

0
H2Ojile

Vous n'avez pas besoin d'expressions rationnelles pour obtenir ce dont vous avez besoin:

'1,200.00'.tr('.','!').tr(',','.').tr('!', ',')

  • Les périodes deviennent des franges (1,200!00)
  • Les virgules deviennent des points (1.200!00)
  • Bangs deviennent des virgules (1.200,00)
0