156

How can I extract a substring from within a string in Ruby?

Example:

String1 = "<name> <substring>"

I want to extract substring from String1 (i.e. everything within the last occurrence of < and >).

5 Answers 5

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

No need to use scan, if we need only one result.
No need to use Python's match, when we have Ruby's String[regexp,#].

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

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

Sign up to request clarification or add additional context in comments.

9 Comments

No need to discredit other perfectly valid (and might I opine, more readable) solutions.
@coreyward, if they are better, please, argument it. For example, sepp2k's solution is more flexible, and that's why I pointed if we need only one result in my solution. And match()[] is slower, because it's two methods instead of one.
This is the fastest of all the methods presented, but even the slowest method takes only 4.5 microseconds on my machine. I do not care to speculate why this method is faster. In performance, speculation is useless. Only measurement counts.
I find this solution more straightforward and to the point (since I am new to Ruby). Thanks.
@Nakilon Readability can outweigh tiny performance differences when considering the overall success of a product and team, so coreyward made a valid comment. That said, I think string[regex] can be just as readable in this scenario, so that's what I used personally.
|
152
String1.scan(/<([^>]*)>/).last.first

scan creates an array which, for each <item> in String1 contains the text between the < and the > in a one-element array (because when used with a regex containing capturing groups, scan creates an array containing the captures for each match). last gives you the last of those arrays and first then gives you the string in it.

Comments

26

You can use a regular expression for that pretty easily…

Allowing spaces around the word (but not keeping them):

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

Or without the spaces allowed:

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

2 Comments

I'm not sure that the last <> actually needs to be the last thing in the string. If e.g. the string foo <bar> baz is allowed (and supposed to give the result bar), this will not work.
I just went based on the sample string he provided.
12

Here's a slightly more flexible approach using the match method. With this, you can extract more than one string:

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"

Comments

7

A simpler scan would be:

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.