jontly
jontly

Reputation: 238

Regex exclude closing bracket

I'm looking to match the final number inside a set of square brackets in a string and pull it out for use elsewhere

[PROJECT-141] This is the task name
^^ Should get **141**
[PROJECT2-222] Let's be tricky and add an extra number 22
^^ Should get **222**

I have a regex which is pretty close - it picks up the final number. But it's also including the closing ] in the match. I've fiddled around with match groups, but with no joy.

This is going into a Ruby project when it works. Here's the best I have so far:

\[*(\d+)\]

It matches:

141]
222]

Upvotes: 0

Views: 777

Answers (3)

Arup Rakshit
Arup Rakshit

Reputation: 118271

Do using String#[] method :

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.

'[PROJECT2-222]'[/\[.*-(\d+)\]/,1] # => "222"
'[PROJECT-141]'[/\[.*-(\d+)\]/,1] # => "141"

Upvotes: 2

the Tin Man
the Tin Man

Reputation: 160549

I'd use:

project_ids = [
"[PROJECT-141] This is the task name",
"[PROJECT2-222] Let's be tricky and add an extra number 22",
].map { |s|
  s[/-(\d+)\]/, 1]
} 
project_ids # => ["141", "222"]

This is the sort of task a regex is designed for. \d is a digit, 0..9. \d+ is one or more digits. We need some place-holders to figure out where in the string to search, so using - which precedes the number, and ] which follows it, is sufficient for the examples given.

The magic occurs in the map block, using s[/-(\d+)\]/, 1], which is a simple way of saying:

  1. Look inside the string for something matching the pattern.
  2. The capture group (\d+) tells the engine to remember that part of the pattern, which is then returned using the 1 parameter. It's all part of String#[].

Upvotes: 1

Stoic
Stoic

Reputation: 10754

My Take:

try this regex: /\[.*-(\d+)\]/

Here is the console tryout inside pry for the above regex:

[1] pry(main)> str = "[PROJECT-141] This is the task name"
# => "[PROJECT-141] This is the task name"
[2] pry(main)> match = str.match(/\[.*-(\d+)\]/)
#=> #<MatchData "[PROJECT-141]" 1:"141">
[3] pry(main)> match[1]
#=> 141

Your Take:

Also, your regex is correct too. Only difference is that it matches 141], but the first match, i.e. match[1] will give you the required integers, i.e. 141.

Here is the console tryout inside pry for your regex:

[4] pry(main)> str = "[PROJECT-141] This is the task name"
# => "[PROJECT-141] This is the task name"
[5] pry(main)> match = str.match(/\[*(\d+)\]/)
#=> #<MatchData "141]" 1:"141">
[6] pry(main)> match[1]
#=> 141

Probably, a function? :P

Here is a quick function you can create using the above:

# will output 0, if it could not find a match for the project's id
def extract_project_ids(*args)
  args.map { |task| task.match(/\[.*-(\d+)\]/)[1] rescue 0 }
end

task1 = "[PROJECT-141] This is the task name"
task2 = "[PROJECT2-222] Let's be tricky and add an extra number 22"
extract_project_ids(task1, task2)
# => [ 141, 222 ]

Upvotes: 0

Related Questions