0

From a string:

"(book(1:3000))"

I need to exclude opening and closing brackets and match:

"book(1:3000)"

using regular expression.

I tried this regular expression:

/([^',()]+)|'([^']*)'/

which detects all characters and integers excluding brackets. The string detected by this regex is:

"book 1:3000"

Is there any regex that disregards the opening and closing brackets, and gives the entire string?

sawa
  • 165,429
  • 45
  • 277
  • 381
Thananjaya S
  • 1,451
  • 4
  • 18
  • 31
  • 2
    Why is this tagged [tag:ruby-on-rails]? – Amadan Jun 15 '18 at 10:11
  • 1
    @Amadan in a hope Rails provides some magic, like a dedicated method doing exactly that? – Aleksei Matiushkin Jun 15 '18 at 10:12
  • It would probably help if you could provide some _context_. For example, what does that string represent, where does it come from, what is `book(...)` (looks like a function call), what is `1:3000`, what's the pattern that you want to match (explain it or show some examples), is there always an additional pair of parentheses surrounding the substring you're interested in? – Stefan Jun 15 '18 at 10:32
  • 1
    instead of regex black magic, you could just do `new_str = str[1..-2]` or maybe `new_str = str.start_with?('(') ? str[1..-2] : str` if that is what your data consistently looks like. – Kimmo Lehto Jun 15 '18 at 13:14

2 Answers2

2

Build the regexp that explicitly states exactly what you want to extract: alphanumerics, followed by the opening parenthesis, followed by digits, followed by a colon, followed by digits, followed by closing parenthesis:

'(book(1:3000))'[/\w+\(\d+:\d+\)/]
#⇒ "book(1:3000)"
Aleksei Matiushkin
  • 119,336
  • 10
  • 100
  • 160
  • No Sir, It is not working. Here is the link `http://rubular.com/r/RipuLVfSXy` for the tested `regex`. – Thananjaya S Jun 15 '18 at 09:57
  • 2
    Sure it works. The link contains some crap that has nothing to do with a regexp I provided. – Aleksei Matiushkin Jun 15 '18 at 10:00
  • 1
    @ThananjayaChakravarthy the square brackets belong to the [method](http://ruby-doc.org/core-2.5.1/String.html#method-i-5B-5D), not the regexp. It's `str[regexp]` with `str` being `'(book(1:3000))'` and `regexp` being `/\w+\(\d+:\d+\)/`. Here's a working example: http://rubular.com/r/7UpYX5ijQS – Stefan Jun 15 '18 at 10:19
2
"(book(1:3000))"[/^\(?(.+?\))\)?/, 1]
=> "book(1:3000)"
"book(1:3000)"[/^\(?(.+?\))\)?/, 1]
=> "book(1:3000)"

The regex split on multiple lines for easier reading:

/
 ^      # start of string
  \(?   # character (, possibly (?)
  (     # start capturing
    .+? # any characters forward until..
    \)  # ..a closing bracket
  )     # stop capturing
/x      # end regex with /x modifier (allows splitting to lines)

1. Look for a possible ( in the beginning of string and ignore it. 2. Start capturing 3. Capture until and including the first )

But this is where it fails:

"book(1:(10*30))"[/^\(?(.+?\))\)?/, 1]
=> "book(1:(10*30)"

If you need something like that, you probably need to use a recursive regex as described in another stackoverflow answer.

Kimmo Lehto
  • 5,910
  • 1
  • 23
  • 32