2012-08-22 3 views
20

Je voudrais patcher certaines données de texte extraites de pages Web. échantillon:Comment faire une référence arrière dans l'expression rationnelle Ruby (regex) avec gsub quand j'utilise le groupement?

t="First sentence. Second sentence.Third sentence." 

Il n'y a pas d'espace après le point à la fin de la deuxième phrase. Cela me signe que la 3ème phrase était dans une ligne séparée (après une étiquette br) dans le document original. Je souhaite utiliser cette expression rationnelle pour insérer le caractère "\ n" aux endroits appropriés et corriger mon texte. Mon regex:

t2=t.gsub(/([.\!?])([A-Z1-9])/,$1+"\n"+$2) 

Mais malheureusement, il ne fonctionne pas: « NoMethodError: méthode non définie + » pour nil: NilClass » Comment puis-je bien aux référence arrière groupes appariés? C'était si facile dans Microsoft Word, je devais juste utiliser les symboles \ 1 et \ 2.

+2

Les globaux numérotés ('$ 1',' $ 2', ...) ne sont pas définis lorsque le second argument est évalué, ils sont définis par 'gsub' avant de céder au bloc. D'où le conseil de sawa sur le moment d'utiliser ''\' 'et quand utiliser' $ 1'. –

Répondre

27

Vous pouvez effectuer une référence arrière dans la chaîne de substitution avec \1 (pour correspondre au groupe de capture 1).

t = "First sentence. Second sentence.Third sentence!Fourth sentence?Fifth sentence." 
t.gsub(/([.!?])([A-Z1-9])/, "\\1\n\\2") # => "First sentence. Second sentence.\nThird sentence!\nFourth sentence?\nFifth sentence." 
19
  • Si vous utilisez gsub(regex, replacement), puis utilisez '\1', '\2', ... pour désigner le match. Assurez-vous de ne pas mettre de guillemets autour du replacement, ou bien d'échapper à la barre oblique inverse comme dans la réponse de Joshua. La conversion de '\1' au match se fera au gsub, et non par interprétation littérale.
  • Si vous utilisez gsub(regex){replacement}, puis utilisez $1, $1 ...

Mais pour votre cas, il est plus facile de ne pas utiliser matches:

t2 = t.gsub(/(?<=[.\!?])(?=[A-Z1-9])/, "\n") 
+1

Il devra utiliser des guillemets doubles pour obtenir le retour à la ligne ou ''\ 1' +" \ n "+ '\ 2''. –

+0

@muistooshort L'OP utilise à l'origine '+', donc ce que vous avez donné correspond à ce que j'avais en tête. – sawa

6

Si vous avez ici à cause de Rubocop se plaignant "Évitez l'utilisation de backrefs de style Perl." environ 1 $, 2 $, etc ... vous pouvez pouvez le faire à la place:

some_id = $1 
# or 
some_id = Regexp.last_match[1] if Regexp.last_match 

some_id = $5 
# or 
some_id = Regexp.last_match[5] if Regexp.last_match 

Il aurez également vous faire

%r{//}.match(some_string) 

au lieu de

some_string[//] 

Boiteux (Rubocop

Questions connexes