Senica Gonzalez
Senica Gonzalez

Reputation: 8182

Get the top level directory name from a filepath string

I really don't know what my problem is lately, but Regex seems to be giving me the most trouble.

Very simple thing I need to do, but can't seem to get it:

I have a uri that returns either /xmlfeed or /xmlfeed/what/is/this

I want to match /xmlfeed on any occasion.

I've tried many variations of the following:

preg_match('/(\/.*?)\/?/', $_SERVER['REQUEST_URI'], $match);

I would read this as: Match forwardslash then match any character until you come to an optional forwardslash.

Upvotes: 0

Views: 143

Answers (6)

Senica Gonzalez
Senica Gonzalez

Reputation: 8182

Using the suggestions posted, I ended up trying this:

echo $_SERVER['REQUEST_URI'];
preg_match("/(\/.*)[^\/]/", $_SERVER['REQUEST_URI'], $match);
$url = "http://".$_SERVER['SERVER_NAME'].$match[0];
foreach($match as $k=>$v){
  echo "<h1>$k - $v</h1>";
}

I also tried it without the .* and without the parentheses.

Without the .* AND () it returns the / with the next character ONLY.

Like it is, it just returns the entire URI everytime

So, when ran with the code above, the output is

/tea-time-blog/post/20 0 - /tea-time-blog/post/20 1 - /tea-time-blog/post/2

This code is being eval()'d by the way. I don't think that should make any differnce in the way PHP handles the regular expression.

Upvotes: 0

Quentin
Quentin

Reputation: 943175

In PHP: '/(\/.*?)\/?/' is a string containing a regular expression.

First you have to decode the string: /(/.*?)\/?/

So you have a forward slash that starts the result expression. An opening brace. A forward slash that ends the matching part of the expression … and I'm pretty sure that it will then error since you haven't closed the brace.

So, to get this working:

  • Remember to escape characters with special meanings in strings and regular expressions
  • Don't confuse the forward slash / with the backslash \

You want to match everything after and including the first slash, but before any (optional) second slash (so we don't want the ? that makes it non-greedy):

/(\/[^\/]*)/

Which, expressed as a PHP string is:

'/(\\/([^\\/]*)/'

Upvotes: 1

Alan Moore
Alan Moore

Reputation: 75222

Your problem is the reluctant quantifier. After the initial slash is matched, .*? consumes the minimum number of characters it's allowed to, which is zero. Then /? takes over; it doesn't see a slash in the next position (which is immediately after the first slash), but that's okay because it's optional. The result: the regex always matches a single slash, and group #1 always matches an empty string.

Obviously, you can't just replace the reluctant quantifier with a greedy one. But if you replace the .* with something that can't match a slash, you don't have to worry about greediness. That's what K Prime's regex, '#/[^/]+#' does. Notice as well how it uses # as the regex delimiter and avoids the necessity of escaping slashes within the regex.

Upvotes: 1

K Prime
K Prime

Reputation: 5849

Why not:

preg_match ('#/[^/]+#', _SERVER['REQUEST_URI'], $match);

?

$match[0] will give you what you need

Upvotes: 2

ghostdog74
ghostdog74

Reputation: 342313

why do you need regex that make you confused??

$string = "/xmlfeed/what/is/this";
$s = explode("/",$string,3);
print "/".$s[1]."\n";

output

$ php test.php
/xmlfeed

Upvotes: 2

pavium
pavium

Reputation: 15108

I know this is avoiding the regex, and therefore avoids the question, but how about splitting the uri (at slashes) into an array.

Then you can deal with the elements of the array, and ignore the bits of the uri you don't want.

Upvotes: 0

Related Questions