Reputation: 227
I've read somewhere today that regex tag in SO gets most "give me ze code" type questions, so I was cautious in asking... I tried, but if this is a duplicate please let me know so I can delete.
[First]sometext[Second]
I would like to use Regex in Ruby to return value between second []:
Second
I so far have:
(?<=\[)(.*)(?=\])
which returns
First]sometext[Second
\[.*?(\[)
this grouping will return
[First]sometext[
so I've been struggling to somehow mix the two but no luck.. hope someone can help.
The closest reference I can find in SO was searched with "match second or nth occurence in regex" which I couldn't get it to work on my issue.
my workaround was to use gsub to replace the [First]
with "" to the initial string with:
\[(.*?)\]
and then do another match.. but I would like know how it can be done with on regex usage.
Upvotes: 2
Views: 1519
Reputation: 110675
Here's a way that may be more convenient if you just want the text enclosed by the last [..]
in a string that may contain any number of [..]
's. [Edit: I'll leave this, but @OnlineCop has a better solution for the objective I described in the previous sentence. It's also an excellent answer to the original question.]
Reverse the string, then search for a substring with a regex that captures ]
in the non-capture group (?:\])
, captures *.?
in capture group 1 (the ?
making it non-greedy) and captures [
in a second non-capture group. Lastly, retrieve and reverse the string contained in capture group 1:
str = "The [first] time I was mad. The [second] time I was irate!"
str.reverse[/(?:\])(.*?)(?:\[)/,1].reverse #=> "second"
Upvotes: 0
Reputation: 3789
There's a lot of ways to handle this. One that hasn't been mentioned yet is the end of input anchor $
.
s = "[First]sometext[Second]"
s.match(/[\[][^\[]+[\]]$/) # => #<MatchData "[Second]">
s.match(/[\[]([^\[]+)[\]]$/) # => #<MatchData "[Second]" 1:"Second">
This only works in the specific case where [something]
ends your string.
The section on 'anchors' describes the subtle differences between $
and \z
and \Z
.
http://www.ruby-doc.org/core-2.1.2/Regexp.html
Upvotes: 2
Reputation: 4069
Why not use a greedy search at the beginning .*
so capture as much as possible?
^.*\[(.*?)\]
You could then make it un-greedy (to capture only the stuff in the first [...] block) by appending ?
as ^.*?
.
Upvotes: 3
Reputation: 3625
You were close. Use this to capture the relevant section in the first capturing group, then access it with $1
.*?\[.*?\[(.*?)\].*
Upvotes: 0
Reputation: 19879
> s = "ipsum[First]sometext[Second]lorem"
=> "ipsum[First]sometext[Second]lorem"
> s =~ /\[.*?\].*?\[(.*?)\]/
=> 5
> $1
=> "Second"
Upvotes: 4