2012-08-22 6 views
20

Chciałbym załatać niektóre dane tekstowe wyodrębnione ze stron internetowych. próbki:Jak cofnąć referencję w wyrażeniu regularnym Rubinowym (regex) za pomocą gsub, gdy używam grupowania?

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

nie ma miejsca po kropce na końcu zdania drugiego. To oznacza, że ​​trzecie zdanie znajdowało się w oddzielnym wierszu (po tagu br) w oryginalnym dokumencie.

Chcę użyć tego wyrażenia regularnego, aby wstawić znak "\ n" w odpowiednie miejsca i załatać mój tekst. Moje regex:

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

Ale niestety to nie działa: "NoMethodError: metoda niezdefiniowany` +”do zera: NilClass" Jak mogę poprawnie wsteczną do dopasowanych grup? W programie Microsoft Word było tak łatwo, wystarczyło użyć symboli \ 1 i \ 2.

+2

Numerowane globale ('$ 1',' $ 2', ...) nie są ustawiane, gdy drugi argument jest oceniany, są one ustawiane przez 'gsub' zanim ulegnie blokowi. Dlatego Sawa radzi, kiedy należy używać '\ 1'' i kiedy używać' $ 1'. –

Odpowiedz

27

Możesz cofnąć referencję w łańcuchu podstawiania za pomocą \1 (aby dopasować grupę przechwytywania 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
  • Jeśli używasz gsub(regex, replacement), a następnie użyć '\1', '\2' ... odnosi się do meczu. Upewnij się, że nie umieszczasz podwójnych cudzysłowów wokół replacement, ani nie uciekniesz tylnemu ukośnikowi, jak w odpowiedzi Joshuy. Konwersja z '\1' na mecz zostanie przeprowadzona w ciągu gsub, a nie w dosłownym tłumaczeniu.
  • Jeśli używasz gsub(regex){replacement}, a następnie użyć $1, $1 ...

Ale w Twoim przypadku, łatwiej jest, aby nie używać mecze:

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

Będzie musiał użyć podwójnych cudzysłowów, aby uzyskać znak nowej linii lub '' \ 1 '+ "\ n" +' \ 2''. –

+0

@muistooshort OP używa pierwotnie '+', więc to, co dałeś, było tym, co miałem na myśli. – sawa

6

Jeśli masz tutaj z powodu Rubocop narzeka "Unikaj używania backrefów w stylu Perla." o $ 1, $ 2, itd ... można to zrobić może zamiast:

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 

Będzie również chcą Ci zrobić

%r{//}.match(some_string) 

zamiast

some_string[//] 

Lame (Rubocop)

Powiązane problemy