Extrahieren Sie einen Teilstring mit einem regulären Ausdruck aus einem String in Ruby


130

Wie kann ich in Ruby einen Teilstring aus einem String extrahieren?

Beispiel:

String1 = "<name> <substring>"

Ich möchte extrahieren substring aus String1(dh alles , was in den letzten Vorkommen <und >).

Antworten:


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

scanErstellt ein Array, das für jedes <item>In String1den Text zwischen dem <und dem >in einem Ein-Element-Array enthält (da bei Verwendung mit einem regulären Ausdruck, der Erfassungsgruppen enthält, der Scan ein Array erstellt, das die Erfassungen für jede Übereinstimmung enthält). lastgibt Ihnen das letzte dieser Arrays und firstgibt Ihnen dann die Zeichenfolge darin.


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

Keine Notwendigkeit zu verwenden scan, wenn wir nur ein Ergebnis benötigen.
Keine Notwendigkeit, Pythons zu verwenden match, wenn wir Rubys haben String[regexp,#].

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

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


37
Keine Notwendigkeit, andere vollkommen gültige (und vielleicht besser lesbare) Lösungen zu diskreditieren.
Coreyward

41
@coreyward, wenn sie besser sind, argumentieren Sie es bitte. Zum Beispiel ist die Lösung von sepp2k flexibler, und deshalb habe ich if we need only one resultin meiner Lösung darauf hingewiesen . Und match()[]ist langsamer, weil es zwei Methoden statt einer sind.
Nakilon

4
Dies ist die schnellste aller vorgestellten Methoden, aber selbst die langsamste Methode benötigt auf meinem Computer nur 4,5 Mikrosekunden. Ich möchte nicht spekulieren, warum diese Methode schneller ist. In der Leistung ist Spekulation nutzlos . Nur die Messung zählt.
Wayne Conrad

8
Ich finde diese Lösung einfacher und auf den Punkt (da ich neu bei Ruby bin). Vielen Dank.
Ryan H.

@Nakilon Die Lesbarkeit kann winzige Leistungsunterschiede überwiegen, wenn man den Gesamterfolg eines Produkts und eines Teams betrachtet. Daher hat coreyward einen gültigen Kommentar abgegeben. Trotzdem denke ich, dass string[regex]es in diesem Szenario genauso lesbar sein kann, also habe ich es persönlich verwendet.
Nick

24

Sie können dafür ganz einfach einen regulären Ausdruck verwenden ...

Leerzeichen um das Wort herum zulassen (aber nicht behalten):

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

Oder ohne die erlaubten Leerzeichen:

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

1
Ich bin mir nicht sicher, ob das Letzte <>tatsächlich das Letzte in der Zeichenfolge sein muss. Wenn zB die Zeichenfolge foo <bar> bazzulässig ist (und das Ergebnis liefern soll bar), funktioniert dies nicht.
sepp2k

Ich habe mich nur an der von ihm bereitgestellten Beispielzeichenfolge orientiert.
Coreyward

10

Hier ist ein etwas flexiblerer Ansatz mit der matchMethode. Mit dieser Option können Sie mehr als eine Zeichenfolge extrahieren:

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"

3

Ein einfacherer Scan wäre:

String1.scan(/<(\S+)>/).last
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.