2010-11-06 4 views

Odpowiedz

90
String1.scan(/<([^>]*)>/).last.first 

scan tworzy tablicę, która dla każdego <item> w String1 zawiera tekst pomiędzy < i > w tablicy jednego elementu (z powodu, gdy stosuje się wyrażenie regularne zawierające grupy przechwytywania skanowania tworzy tablicę zawierającą przechwytuje dla każdego meczu). last podaje ostatnią z tych tablic i first, a następnie podaje w niej ciąg znaków.

13

Można użyć wyrażenia regularnego do tego dość łatwo ...

Umożliwienie przestrzenie wokół słowa (ale nie ich utrzymanie):

str.match(/< ?([^>]+) ?>\Z/)[1] 

lub bez spacji dozwolony:

str.match(/<([^>]+)>\Z/)[1] 
+1

nie jestem pewien, że ostatni '<>' faktycznie musi być ostatnią rzeczą w ciąg znaków. Jeśli np. ciąg 'foo baz' jest dozwolony (i ma dać wynik' bar'), to nie zadziała. – sepp2k

+0

Po prostu wyszedłem na podstawie przykładowego ciągu, który podał. – coreyward

228
"<name> <substring>"[/.*<([^>]*)/,1] 
=> "substring" 

Nie trzeba używać scan, jeśli potrzebujemy tylko jednego wyniku.
Nie trzeba używać match, gdy mamy String[regexp,#].

Patrz: http://ruby-doc.org/core/String.html#method-i-5B-5D

Uwaga: str[regexp, capture] → new_str or nil

+24

Nie ma potrzeby dyskredytowania innych, całkowicie ważnych (i mogących być bardziej przejrzystymi) rozwiązań. – coreyward

+27

@coreyward, jeśli są lepsze, proszę, spróbuj. Na przykład rozwiązanie sepp2k jest bardziej elastyczne i dlatego wskazałem "jeśli potrzebujemy tylko jednego wyniku" w moim rozwiązaniu. A funkcja 'match() []' jest wolniejsza, ponieważ jest to dwie metody zamiast jednej. – Nakilon

+1

Jestem tutaj, aby pomóc, a nie kłócić się. Wywołanie dwóch metod * jest * wolniejsze, ale o tyle nieskończenie małe, że wymagałoby setek milionów iteracji, aby uzyskać wymierny efekt. Nie ma jednego "właściwego" rozwiązania jakiegokolwiek problemu. – coreyward

8

Oto nieco bardziej elastyczne podejście stosując metodę match. Dzięki temu można wyodrębnić więcej niż jeden łańcuch:

s = "<ants> <pants>" 
matchdata = s.match(/<([^>]*)> <([^>]*)>/) 

# Use 'captures' to get an array of the captures 
matchdata.captures # ["ants","pants"] 

# Or use raw indices 
matchdata[0] # whole regex match: "<ants> <pants>" 
matchdata[1] # first capture: "ants" 
matchdata[2] # second capture: "pants" 
1

Prostsze skanowanie będzie:

String1.scan(/<(\S+)>/).last