2010-11-06 4 views

risposta

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

scan crea una matrice che, per ogni <item> in String1 contiene il testo tra il < e > in una matrice elemento (perché quando utilizzato con un regex contenente gruppi di cattura, scansione crea una matrice contenente la cattura per ogni partita). last ti dà l'ultimo di questi array e first ti dà la stringa in esso.

13

È possibile utilizzare un'espressione regolare per questo abbastanza facilmente ...

Permettere spazi intorno alla parola (ma non il loro mantenimento):

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

O senza gli spazi domestici:

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

non sono sicuro che l'ultimo '<>' in realtà deve essere l'ultima cosa a la stringa. Se ad es. la stringa 'foo baz' è consentita (e dovrebbe dare il risultato' bar'), questo non funzionerà. – sepp2k

+0

Mi sono basato sulla stringa di esempio che ha fornito. – coreyward

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

Non è necessario utilizzare scan, se è necessario un solo risultato.
Non è necessario utilizzare match, quando abbiamo String[regexp,#].

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

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

+24

Non c'è bisogno di screditare altre soluzioni perfettamente valide (e potrei opporre, più leggibili). – coreyward

+27

@coreyward, se sono migliori, per favore, discutilo. Ad esempio, la soluzione di sepp2k è più flessibile, ed è per questo che ho indicato "se abbiamo bisogno di un solo risultato" nella mia soluzione. E 'match() []' è più lento, perché sono due metodi invece di uno. – Nakilon

+1

Sono qui per aiutare, non per litigare. Chiamare due metodi * è * più lento, ma con una quantità così infinita che ci vorrebbero centinaia di milioni di iterazioni per avere effetti misurabili. Non esiste un'unica soluzione "giusta" per qualsiasi problema. – coreyward

8

Ecco un approccio leggermente più flessibile utilizzando il metodo match. Con questo, è possibile estrarre più di una stringa:

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

Una scansione più semplice potrebbe essere:

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