简体   繁体   中英

ruby regex match from end of string

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.

> s = "ipsum[First]sometext[Second]lorem"
=> "ipsum[First]sometext[Second]lorem"
> s =~ /\[.*?\].*?\[(.*?)\]/
=> 5
> $1
=> "Second"

Why not use a greedy search at the beginning .* so capture as much as possible?

^.*\[(.*?)\]

Demo

You could then make it un-greedy (to capture only the stuff in the first [...] block) by appending ? as ^.*? .

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

You were close. Use this to capture the relevant section in the first capturing group, then access it with $1

.*?\\[.*?\\[(.*?)\\].*

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"

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM