2012-08-22 11 views
20

Ich möchte einige Textdaten patchen, die von Webseiten extrahiert werden. Beispiel:Wie referenziere ich in regulärem Ruby-Ausdruck (regex) mit gsub, wenn ich Gruppierung verwende?

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

Es gibt keinen Raum nach dem Punkt am Ende des zweiten Satzes. Dies bedeutet, dass der 3. Satz in einer separaten Zeile (nach einem br-Tag) im Originaldokument steht.

Ich möchte diese Regexp verwenden, um "\ n" Zeichen an den richtigen Stellen einzufügen und meinen Text zu patchen. Meine regex:

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

Aber leider funktioniert es nicht: „NoMethodError: nicht definierte Methode` +‘für Null: NilClass“ Wie kann ich zu den angepassten Gruppen Rückreferenzierung richtig? Es war so einfach in Microsoft Word, ich musste einfach \ 1 und \ 2 Symbole verwenden.

+2

Die nummerierten Globals ('$ 1',' $ 2', ...) werden nicht gesetzt, wenn das zweite Argument ausgewertet wird, sie werden mit 'gsub' gesetzt, bevor es dem Block nachgibt. Daher sawas Ratschlag, wann man '' \ 1'' und wann '$ 1' verwenden soll. –

Antwort

27

Sie können in der Ersetzungszeichenfolge mit \1 (um die Erfassungsgruppe 1 abzugleichen) rückreferenzieren.

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
  • Wenn Sie gsub(regex, replacement) verwenden, dann verwenden '\1', '\2', ... auf das Spiel zu beziehen. Stellen Sie sicher, dass Sie keine Anführungszeichen um die replacement setzen oder den umgekehrten Schrägstrich wie in Joshuas Antwort vermeiden. Die Konvertierung von '\1' zum Match erfolgt innerhalb von gsub, nicht durch wörtliche Interpretation.
  • Wenn Sie gsub(regex){replacement} verwenden, verwenden Sie dann $1, $1, ...

Aber für Ihren Fall, es ist einfacher, nicht Streichhölzer zu verwenden:

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

Er muss doppelte Anführungszeichen verwenden, um den Zeilenumbruch oder '\ 1 '+" \ n "+' \ 2'' zu erhalten. –

+0

@muistooshort Das OP verwendet ursprünglich '+', also was Sie gaben, war, was ich im Sinn hatte. – sawa

6

Wenn Sie hier bekam wegen Rubocop beschweren sich: "Vermeiden Sie die Verwendung von Perl-Backreferences." etwa $ 1, $ 2, etc ... können Sie diese stattdessen tun:

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 

Es sollten Sie auch

%r{//}.match(some_string) 

statt

some_string[//] 

Lame (Rubocop tun)