Return First Match of Ruby Regex

Return first match of Ruby regex

You could try String#[] (as in variableName[/regular expression/]).

This is an example output from IRB:

names = "erik kalle johan anders erik kalle johan anders"
# => "erik kalle johan anders erik kalle johan anders"
names[/kalle/]
# => "kalle"

How to return first match sub-string of a string using Ruby regex?

scan will return all substrings that matches the pattern. You can use match, scan or [] to achieve your goal:

report_path = '/usr/share/filebeat/reports/ui/local/20200904_151507/API/API_Test_suite/20200904_151508/20200904_151508.csv'

report_path.match(/\d{8}_\d{6}/)[0]
# => "20200904_151507"

report_path.scan(/\d{8}_\d{6}/)[0]
# => "20200904_151507"

# String#[] supports regex
report_path[/\d{8}_\d{6}/]
# => "20200904_151507"

Note that match returns a MatchData object, which may contains multiple matches (if we use capture groups). scan will return an Array containing all matches.

Here we're calling [0] on the MatchData to get the first match


Capture groups:

Regex allow us to capture multiples substring using one patern. We can use () to create capture groups. (?'some_name'<pattern>) allow us to create named capture groups.

report_path = '/usr/share/filebeat/reports/ui/local/20200904_151507/API/API_Test_suite/20200904_151508/20200904_151508.csv'

matches = report_path.match(/(\d{8})_(\d{6})/)
matches[0] #=> "20200904_151507"
matches[1] #=> "20200904"
matches[2] #=> "151507"


matches = report_path.match(/(?'date'\d{8})_(?'id'\d{6})/)
matches[0] #=> "20200904_151507"
matches["date"] #=> "20200904"
matches["id"] #=> "151507"

We can even use (named) capture groups with []

From String#[] documentation:

If a Regexp is supplied, the matching portion of the string is returned. If a capture follows the regular expression, which may be a capture group index or name, follows the regular expression that component of the MatchData is returned instead.

report_path = '/usr/share/filebeat/reports/ui/local/20200904_151507/API/API_Test_suite/20200904_151508/20200904_151508.csv'

# returns the full match if no second parameter is passed
report_path[/(\d{8})_(\d{6})/]
# => 20200904_151507

# returns the capture group n°2
report_path[/(\d{8})_(\d{6})/, 2]
# => 151507

# returns the capture group called "date"
report_path[/(?'date'\d{8})_(?'id'\d{6})/, 'date']
# => 20200904

How do I find the first occurrence of a regex in Ruby?

You may use

first_occurrence = s =~ /regex/

If the result is not nil, it contains the index of the first match. See the Ruby demo.

See Ruby 2.4 documentation:

=~ is Ruby's basic pattern-matching operator. ... If a match is found, the operator returns index of first match in string, otherwise it returns nil.

Ruby str.match(regex) returns MatchData containing only first matched item

It seems that MatchData returned by .match() method only returns the first match with all captured groups if any. I have just tested it and I only could get 1 match with .match().

See Regular-Expressions.info details:

To test if a particular regex matches (part of) a string, you can
either use the =~ operator, call the regexp object's match() method,
e.g.: print "success" if subject =~ /regex/ or print "success" if
/regex/.match(subject).

Also, from here:

String.=~(Regexp) returns the starting position of the first match or
nil if no match was found

To obtain all matches, you need to use .scan() method.

Ruby - How to return matched Regexp value

Try with this

pattern = Regexp.union(['+', '-']) #=> /\+|\-/

using operator

['foo', '+', 'bar'].select{ |e| e =~ pattern }
=>["+"]

using match? method

['foo', '+', 'bar'].select{ |e| e.match?(pattern) 
=>["+"]

using String#[]

['foo', '+', 'bar'].select{ |e| e[pattern] }
=>["+"]

RegExp#match returns only one match

You need to use .scan() to match more than once:

p s.scan(/a/).to_a

And with grouping, you get one result for the overall match, and one for each group (when using .match(). Both results are the same in your regex.

Some examples:

> /(a)/.matc­h(s).to_a
=> ["a", "a"] # First: Group 0 (overall match), second: Group 1
> /(a)+/.mat­ch(s).to_a­
=> ["aaaa", "a"] # Regex matches entire string, group 1 matches the last a
> s.scan(/a/­).to_a
=> ["a", "a", "a", "a"] # Four matches, no groups
> s.scan(/(a­)/).to_a
=> [["a"], ["a"], ["a"], ["a"]] # Four matches, each containing one group
> s.scan(/(a­)+/).to_a
=> [["a"]] # One match, the last match of group 1 is retained
> s.scan(/(a­+)(a)/).to­_a
=> [["aaa", "a"]] # First group matches aaa, second group matches final a
> s.scan(/(a­)(a)/).to_­a
=> [["a", "a"], ["a", "a"]] # Two matches, both group participate once per match

Regex match everything up to first period

/^([^.]+)/

Let's break it down,

  • ^ is the newline anchor

  • [^.] this matches any character that's not a period

  • \+ to take until a period

And the expression is encapsulated with () to capture it.

Ruby expression to return first x letters and also first word

You don't need to use regular expression.

def first_letters(str, num)
str[0, num]
end


def first_word(str)
str.split[0]
end

Using regular expression:

def first_letters(str, num)
str[Regexp.new("^.{#{num}}")]
end

def first_word(str)
str[/\w+/] # or str[/\S+/]
end

Ruby Regex: Match Until First Occurance of Character

You're missing the ? quantifier to make it a non greedy match. And I would remove | from inside of your character class because it's trying to match a single character in the list (#|@) literally.

/-\s(.*?)(?=[#@])/

See Demo

You really don't need a Positive Lookahead here either, just match up until those characters and print the result from your capturing group.

/-\s(.*?)[#@]/

You could also use negation in this case.

/-\s([^#@]*)/

Ruby: Find first N regex matches in a string (and stop scanning)

Not that elegant, but you could use the block form:

str = 'abcabcabc'

result = []
str.scan(/b/) { |match| result << match; break if result.size >= 2 }
result #=> ["b", "b"]


Related Topics



Leave a reply



Submit