1

I am trying to use sting substitution in a ruby regex that spans over multiple lines. I believe the problem is that in Free-Spacing mode the '#' is seen as a comment.

First of all is there a better way to breakup long regexes and secondly, how should i perform substitutions in Free-Spacing regexes

The code below has 2 examples. get_module_name_a with the regex all on one line that works fine and the get_module_name_b with the free-spacing regex where the substitution ends up being seen as a comment (I think).

Ideally I would like to keep the length of my lines below 80 chars.

The output of the code is currently

$ ruby test.rb 
testmod2
test.rb:42:in `get_module_name_b': undefined method `[]' for nil:NilClass (NoMethodError)
    from test.rb:46:in `<main>'

Sample code:

#!/usr/bin/env ruby

def loadFile
  "
mod 'testmod1',
  :git => '[email protected]:reaktor/testmod1.git',
  :ref => 'RELEASE_1.0.0'

mod 'testmod2',
  :git => '[email protected]:reaktor/myproject-testmod2.git',
  :ref => 'RELEASE_2.0.10'

mod 'testmod3',
  :git => '[email protected]:reaktor/testmod3.git',
  :tag => 'RELEASE_10.2.3'

  "
end

def get_module_name_a(repo_name)
  input_string = loadFile
  regex = /mod ["'](\w*)["'],\s*$\n+(\s*):git\s*=>\s*["'].*#{repo_name}.git["'],$\n+(\s*):ref\s*=>\s*['"](\w+|\w+\.\d+\.\d+)['"]$/
  result = regex.match(input_string)
  result[1]
end

def get_module_name_b(repo_name)
  input_string = loadFile
  regex = /\A
    mod ["'](\w*)["'],\s*$\n
    +(\s*):git\s*=>\s*["'].*#{repo_name}.git["'],$\n
    +(\s*):ref\s*=>\s*['"](\w+|\w+\.\d+\.\d+)['"]$
    \Z/x
  result = regex.match(input_string)
  result[1]
end

puts get_module_name_a('myproject-testmod2')
puts get_module_name_b('myproject-testmod2')
1
  • You are asking two questions that aren't really related except that they're both about regular expressions. Where have you searched to find information about building complex regular expressions from simple ones? Source code is all over the internet that shows how to do it, plus it's installed as part of the Ruby you're using. Search your disk for rfc2396_parser.rb, which is part of URI, and read through that file. It's chock-full of interesting examples. Commented Jan 14, 2016 at 20:48

2 Answers 2

1

Several things to mention here:

  • a literal space should be put into a character class [ ] in /x regex (here, the one after mod)
  • you have $ and \Z together in B method
  • be careful with the quantifiers, keep them next to the patterns they are applied
  • \A in your regex forces to match at the beginning of the string, while the first regex does not have that restriction

Here is a working code:

def get_module_name_b(repo_name)
  input_string = loadFile
  regex = /mod[ ]["'](\w*)["'],\s*$\n+
    (\s*):git\s*=>\s*["'].*#{repo_name}.git["'],$\n+
    (\s*):ref\s*=>\s*['"](\w+|\w+\.\d+\.\d+)['"]
    $/x
  result = regex.match(input_string)
  result[1]
end

See IDEONE demo

You can contract and make more efficient the (\w+|\w+\.\d+\.\d+) regex part if you change it to (\w+(?:\.\d+\.\d+)?).

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

Comments

0

Regexp.new("ab #{'c d'}", Regexp::EXTENDED) will match abcd.

so you could use

regex = Regex.new <<-REGEXP, Regexp::EXTENDED
  \A
  mod ["'](\w*)["'],\s*$\n
  +(\s*):git\s*=>\s*["'].*#{repo_name}.git["'],$\n
  +(\s*):ref\s*=>\s*['"](\w+|\w+\.\d+\.\d+)['"]$
  \Z
REGEXP

Since this uses standard string interpolation, there is no conflict with the x option in this way of defining a regular expression.

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.