Ruby Regexp Group Matching, Assign Variables on 1 Line

Ruby Regexp group matching, assign variables on 1 line

You don't want scan for this, as it makes little sense. You can use String#match which will return a MatchData object, you can then call #captures to return an Array of captures. Something like this:

#!/usr/bin/env ruby

string = "RyanOnRails: This is a test"
one, two, three = string.match(/(^.*)(:)(.*)/i).captures

p one #=> "RyanOnRails"
p two #=> ":"
p three #=> " This is a test"

Be aware that if no match is found, String#match will return nil, so something like this might work better:

if match = string.match(/(^.*)(:)(.*)/i)
one, two, three = match.captures
end

Although scan does make little sense for this. It does still do the job, you just need to flatten the returned Array first. one, two, three = string.scan(/(^.*)(:)(.*)/i).flatten

Ruby - best way to extract regex capture groups?

Since v2.4.6, Ruby has had named_captures, which can be used like this. Just add the ?<some_name> syntax inside a capture group.

/(\w)(\w)/.match("ab").captures # => ["a", "b"]
/(\w)(\w)/.match("ab").named_captures # => {}

/(?<some_name>\w)(\w)/.match("ab").captures # => ["a"]
/(?<some_name>\w)(\w)/.match("ab").named_captures # => {"some_name"=>"a"}

Even more relevant, you can reference a named capture by name!

result = /(?<some_name>\w)(\w)/.match("ab")
result["some_name"] # => "a"

Ruby one-liner to capture regular expression matches

string = "the quick brown fox jumps over the lazy dog."

extract_string = string[/fox (.*?) dog/, 1]
# => "jumps over the lazy"

extract_array = string.scan(/the (.*?) fox .*?the (.*?) dog/).first
# => ["quick brown", "lazy"]

This approach will also return nil (instead of throwing an error) if no match is found.

extract_string = string[/MISSING_CAT (.*?) dog/, 1]
# => nil

extract_array = string.scan(/the (.*?) MISSING_CAT .*?the (.*?) dog/).first
# => nil

Ruby regular expression using variable name

The code you think doesn't work, does:

var = "Value"
str = "a test Value"
p str.gsub( /#{var}/, 'foo' ) # => "a test foo"

Things get more interesting if var can contain regular expression meta-characters. If it does and you want those matacharacters to do what they usually do in a regular expression, then the same gsub will work:

var = "Value|a|test"
str = "a test Value"
str.gsub( /#{var}/, 'foo' ) # => "foo foo foo"

However, if your search string contains metacharacters and you do not want them interpreted as metacharacters, then use Regexp.escape like this:

var = "*This*"
str = "*This* is a string"
p str.gsub( /#{Regexp.escape(var)}/, 'foo' )
# => "foo is a string"

Or just give gsub a string instead of a regular expression. In MRI >= 1.8.7, gsub will treat a string replacement argument as a plain string, not a regular expression:

var = "*This*"
str = "*This* is a string"
p str.gsub(var, 'foo' ) # => "foo is a string"

(It used to be that a string replacement argument to gsub was automatically converted to a regular expression. I know it was that way in 1.6. I don't recall which version introduced the change).

As noted in other answers, you can use Regexp.new as an alternative to interpolation:

var = "*This*"
str = "*This* is a string"
p str.gsub(Regexp.new(Regexp.escape(var)), 'foo' )
# => "foo is a string"

Regexp to match multi-line string

You will need to make last group non-capturing:

^(?<FOOTER_TYPE>[ a-zA-Z0-9-]+)?(?<SEPARATOR>:)?(?<FOOTER>(?<=:)(?:.|[\r\n](?![\r\n]))*)?

Make note of:

(?:.|[\r\n](?![\r\n]))*)?

(?: at the start makes this optional group non-capturing.

Updated Demo

Ruby strange behaviour while single assigning variables in a single line

It first assigns 2 to num_2, then returns a value and puts it into an array that is assigned to num_1

[11] pry(main)> num_1 = 1, num_2 = 2
=> [1, 2]
[12] pry(main)> num_1 = 1, (num_2 = 2)
=> [1, 2]
[13] pry(main)> num_1 = [1, (num_2 = 2)]
=> [1, 2]

If you want to assign two variables in one line, use a semicolon:

[14] pry(main)> num_1 = 1; num_2 = 2
=> 2
[15] pry(main)> num_1
=> 1
[16] pry(main)> num_2
=> 2

Regexp in ruby - can I use parenthesis without grouping?

Use a non-capturing group:

r = /(?:ab)?(cd)/


Related Topics



Leave a reply



Submit