Reputation: 2643
I'm trying to be able to match a phrase like:
I request a single car
// or
I request a single person
// or
I request a single coconut tree
but not
I request a single car by id
// nor
I request a single person by id with friends
// nor
I request a single coconut tree by id with coconuts
Something like this works:
/^I request a single person(?!\s+by id.*)/
for strings like this:
I request a single person
I request a single person with friends
But when I replace the person with a matcher (.*) or add the $ to the end, it stops working:
/^I request a single (.*)(?!\s+by id.*)$/
How can I accomplish this but still match in the first match everything before the negative lookahead?
Upvotes: 1
Views: 391
Reputation: 2643
OK, I think I just got it. Right after asking the question. Instead of a creating lookahead after the thing I want to capture, I create a lookahead before the thing I want to capture, like so:
/^I request a single (?!.*by id.*)(.*[^\s])?\s*$/
Upvotes: 1
Reputation: 110675
There's no )
to match (
in (.*\)
. Perhaps that's a typo, since you tested. After fixing that, however, there's still a problem:
"I request a single car by idea" =~ /^I request a single (?!.*by id.*)(.*)$/
#=> nil
Presumably, that should be a match. If you only want to know if there's a match, you can use:
r = /^I request a single (?!.+?by id\b)/
Then:
"I request a single car by idea" =~ r #=> 0
"I request a single person by id with friends" =~ r #=> nil
\b
matches a word break, which includes the case where the previous character is the last one in the string. Notice that if you are just checking for a match, there's no need to include anything beyond the negative lookahead.
If you want to return whatever follows "single "
when there's a match, use:
r = /^I request a single (?!.+?by id\b)(.*)/
"I request a single coconut tree"[r,1] #=> "coconut tree"
"I request a single person by id with friends"[r,1] #=> nil
Upvotes: 1