3

I just cant seem to be able to figure out how to match the following

in the string /hello/there-my-friend

I need to capture everything after the last / and before the last -

So it should capture there-my.

thomasrutter
  • 114,488
  • 30
  • 148
  • 167
everreadyeddy
  • 738
  • 1
  • 8
  • 18

5 Answers5

2

Here's the Regular Expression you're looking for:

#(?<=/)[^/]+(?=-[^-/]*$)#

I'll break it down in a minute, but there are probably better ways to do this.

I might do something like this:

$str = "/hello/there-my-friend";
$pieces = explode('/', $str);
$afterLastSlash = $pieces[count($pieces)-1];
$dashes = explode('-', $afterLastSlash);
unset($dashes[count($dashes)-1]);
$result = implode('-', $dashes);

The performance here is guaranteed linear (limiting factor being the length of $str plus the length of $afterLastSlash. The regular expression is going to be much slower (as much as polynomial time, I think - it can get a little dicey with lookarounds.)

The code above could easily be pared down, but the naming makes it more clear. Here it is as a one liner:

$result = implode('-', array_slice(explode('-', array_slice(explode('/', $str), -1)), 0, -1));

But gross, don't do that. Find a middle ground.

As promised, a breakdown of the regular expression:

#
    (?<=        Look behind an ensure there's a...
        /       Literal forward slash.
    )           Okay, done looking behind.
    [^/]        Match any character that's not a forward slash
    +           ...One ore more times.
    (?=         Now look ahead, and ensure there's...
        -       a hyphen.
        [^-/]   followed by any non-hyphen, non-forward slash character
        *       zero or more times
        $       until the end of the string.
     )          Okay, done looking ahead.
#
FrankieTheKneeMan
  • 6,645
  • 2
  • 26
  • 37
  • Hm. I conflated this with another question I was considering answering, and wrote the answer with PHP regex in mind. If that's not your flavor, let me know and I'll translate. – FrankieTheKneeMan Mar 20 '13 at 23:00
  • I am using regexpal to test the expression and this does not look to working – everreadyeddy Mar 20 '13 at 23:20
  • Regexpal is javascript. Are you using javascript? Because javascript does not tolerate lookarounds. If you're not using javascript: Try http://gskinner.com/RegExr/. And remember to leave off the delimiters. If you are using javascript, hold on a minute. – FrankieTheKneeMan Mar 20 '13 at 23:27
  • If you are using javascript: `"/hello/there-my-friend".match(/\/([^\/]+)-[^-\/]*$/)[1]` produces `"there-my"`. – FrankieTheKneeMan Mar 20 '13 at 23:30
  • 1
    @everreadyeddy : here's a direct link to the RegExr with this regex. http://regexr.com?34796 – FrankieTheKneeMan Mar 20 '13 at 23:32
  • Looks to be working. Had to change it slightly to get it working on regexpal to [^/]+(?=-[^-/]*$) – everreadyeddy Mar 21 '13 at 00:02
1
^".*/([^/-]*)-[^/-]*$

Syntax may vary depending on which flavor of RE you are using.

Chris Seymour
  • 83,387
  • 30
  • 160
  • 202
Dale Wilson
  • 9,166
  • 3
  • 34
  • 52
1

Try this short regex :

/\K\w+-\w+

Your regex engine need \K support

or

(?<=/)\w+-\w+

(more portable)

Explanations

Community
  • 1
  • 1
Gilles Quénot
  • 173,512
  • 41
  • 224
  • 223
0

This is not an exact answer to your question (its not a regex), but if you are using C# you might use this:

string str = "/hello/there-my-friend";
int lastSlashIndex = str.LastIndexOf('/');
int lastDashIndex = str.LastIndexOf('-');

return str.Substring(lastSlashIndex, lastDashIndex - lastSlashIndex);
Daniel A.A. Pelsmaeker
  • 47,471
  • 20
  • 111
  • 157
0

This will do it:

(?!.*?/).*(?=-)

Depending on your language, you might need to escape the /

Breakdown:

1. (?!.*?/) - Negative look ahead. It will start collecting characters after the last `/`
2. .*       - Looks for all characters
3. (?=-)    - Positive look ahead. It means step 2 should only go up to the last `-`

Edited after comment: No longer includes the / and the last - in the results.

Nick
  • 4,302
  • 2
  • 24
  • 38