0

I have a url, - "http://example.com/sales/view/id/705" and I need get a last segment (705).

How can I do this using PCRE?

reinierpost
  • 8,425
  • 1
  • 38
  • 70
NiLL
  • 13,645
  • 14
  • 46
  • 59
  • using PCRE is a primary words in my question. – NiLL Jan 19 '12 at 13:50
  • `$pattern = '~http://example.com/sales/view/id/([0-9]+)~';` Can you expand a little bit more about why you need a pcre solution? I'm not questioning the need for it.. but your answer could significantly change the solution. – Mike B Jan 19 '12 at 13:53
  • I need to add utm link (Analytics) for special link for this I'm using a preg_match with few rules. – NiLL Jan 19 '12 at 13:57
  • 2
    Everyone who posted so far is assuming it's safe to ignore `http://example.com/sales/view/id/705?foo`, `http://example.com/sales/view/id/705?foo/bar`, `http://example.com/sales/view/id/705#foo` and `http://example.com/sales/view/id/705#foo/bar`. (Only the solution using URI works for these.) Is that truly the case? – ikegami Jan 19 '12 at 20:27

8 Answers8

6

This should do it in Perl:

my ($last) = $url =~ /([^\/]+)\z/;

But I would rather use the URI module:

my $last = (URI->new($url)->path_segments)[-1];
Eugene Yarmash
  • 142,882
  • 41
  • 325
  • 378
  • 3
    Your regex can fail if the URL has a query or fragment, which goes to show why using [URI](http://search.cpan.org/perldoc?URI) is the smart way to go. +1 for mentioning the module. – ikegami Jan 19 '12 at 20:24
4

(In PHP) I would not use PCRE for such a trivial and un-ambiguous job. I would just do:

$parts = explode('/', rtrim($url, '/'));
$partYouWant = array_pop($parts);

EDIT

If you need to use PCRE (although I don't know why you would) this variation on eugene y's answer would do it:

$pattern = '#/([^/]+)\z#';
$url = 'http://example.com/sales/view/id/705';
preg_match($pattern, $url, $matches);
echo $matches[1];
DaveRandom
  • 87,921
  • 11
  • 154
  • 174
4

In PHP you can do this in a single line code:

$url = 'http://example.com/sales/view/id/705';
substr($url, strrpos($url, '/') + 1);
Aurelio De Rosa
  • 21,856
  • 8
  • 48
  • 71
  • +1 - I suspect this would be less costly that my solution and would work in the same way. This may also require the `rtrim($url, '/');` although I only put this in a safe-guard against the URL potentially having a trailing slash, which may not be the case. – DaveRandom Jan 19 '12 at 13:51
  • @DaveRandom I think this is faster too. As you point out it may not work in the case of a '/' at the end of string but it does not seems the case. Anyway seems that someone doesn't like my solution due to the -1 :) – Aurelio De Rosa Jan 19 '12 at 13:58
  • 3
    I got one as well - but what can you do. At least it's costing the downvoter rep to downvote and not explain. I think you should lose -5 if you cast the first downvote and don't comment on the post. – DaveRandom Jan 19 '12 at 14:00
2

Non PCRE alternative:

$url="http://example.com/sales/view/id/705";
$lastPart = current(array_reverse((explode('/',parse_url($url,PHP_URL_PATH)))));

Doubt if it's any faster though

Mark Baker
  • 209,507
  • 32
  • 346
  • 385
2

You could use this pattern ([^\/]*)$ for everything from last / to end.

Maybe also interesting: ([^\/\?]*)(\?.*)?$ gives you everything between last / and first ?

DerVO
  • 3,679
  • 1
  • 23
  • 27
1

Say no to PCRE if you can,:-).

echo basename('http://example.com/sales/view/id/705');
Lake
  • 813
  • 4
  • 6
1

Simplest:

  $ok=preg_match('#\d+$#',$url,$m);
  if($ok)
    echo $m[0],"\n";

Brainy:

  $ok=preg_match('#/(\d+)$#',$url,$m);
  if($ok)
    echo $m[1],"\n";

Flexible: (as it also allows words, other than digits)

  $ok=preg_match('#/(\w+)$#',$url,$m);
  if($ok)
    echo $m[1],"\n";

More flexible: (as it now allows everything that's not a / to match)

  $ok=preg_match('#/(.*?)$#',$url,$m);
  if($ok)
    echo $m[1],"\n";
ZJR
  • 9,308
  • 5
  • 31
  • 38
1
preg_match('@/([1-9]\d*)/?(?:$|\?)@', $url, $matches);//$matches[1] contains your id
Walf
  • 8,535
  • 2
  • 44
  • 59